8 * Copyright (C) 1995 by Paal-Kr. Engstad and Volker Lendecke
10 * 28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per
12 * Modified for big endian support by Christian Starkjohann.
13 * Modified for use with AmigaOS by Olaf Barthel <obarthel -at- gmx -dot- net>
17 #if !defined(__AROS__)
18 #include "quad_math.h"
21 /*****************************************************************************/
24 #include <smb/smbno.h>
25 #include <smb/smb_fs.h>
27 /*****************************************************************************/
29 #define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN)
30 #define SMB_CMD(packet) ((packet)[8])
31 #define SMB_WCT(packet) ((packet)[SMB_HEADER_LEN - 1])
32 #define SMB_BCC(packet) smb_bcc(packet)
33 #define SMB_BUF(packet) ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2)
35 #define SMB_DIRINFO_SIZE 43
36 #define SMB_STATUS_SIZE 21
38 /*****************************************************************************/
40 static INLINE byte
* smb_encode_word(byte
*p
, word data
);
41 static INLINE byte
* smb_decode_word(byte
*p
, word
*data
);
42 static INLINE word
smb_bcc(const byte
*packet
);
43 static INLINE
int smb_verify(const byte
*packet
, int command
, int wct
, int bcc
);
44 static byte
*smb_encode_dialect(byte
*p
, const byte
*name
, int len
);
45 static byte
*smb_encode_ascii(byte
*p
, const byte
*name
, int len
);
46 static void smb_encode_vblock(byte
*p
, const byte
*data
, word len
, int unused_fs
);
47 static byte
*smb_decode_data(const byte
*p
, byte
*data
, word
*data_len
, int fs
);
48 static byte
*smb_name_mangle(byte
*p
, const byte
*name
);
49 static int date_dos2unix(unsigned short time_value
, unsigned short date
);
50 static void date_unix2dos(int unix_date
, unsigned short *time_value
, unsigned short *date
);
51 static INLINE
int smb_valid_packet(const byte
*packet
);
52 static int smb_errno(int errcls
, int error
);
53 static int smb_request_ok(struct smb_server
*s
, int command
, int wct
, int bcc
);
54 static int smb_retry(struct smb_server
*server
);
55 static int smb_request_ok_unlock(struct smb_server
*s
, int command
, int wct
, int bcc
);
56 static byte
*smb_setup_header(struct smb_server
*server
, byte command
, word wct
, word bcc
);
57 static byte
*smb_setup_header_exclusive(struct smb_server
*server
, byte command
, word wct
, word bcc
);
58 static int smb_proc_do_create(struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*entry
, word command
);
59 static char *smb_decode_dirent(char *p
, struct smb_dirent
*entry
);
60 static int smb_proc_readdir_short(struct smb_server
*server
, char *path
, int fpos
, int cache_size
, struct smb_dirent
*entry
);
61 static char *smb_decode_long_dirent(char *p
, struct smb_dirent
*finfo
, int level
);
62 static int smb_proc_readdir_long(struct smb_server
*server
, char *path
, int fpos
, int cache_size
, struct smb_dirent
*entry
);
63 static int smb_proc_reconnect(struct smb_server
*server
);
64 static void smb_printerr(int class, int num
);
66 /*****************************************************************************/
68 /*****************************************************************************
70 * Encoding/Decoding section
72 *****************************************************************************/
74 smb_encode_word (byte
* p
, word data
)
76 p
[0] = data
& 0x00ffU
;
77 p
[1] = (data
& 0xff00U
) >> 8;
82 smb_decode_word (byte
* p
, word
* data
)
84 (*data
) = (word
) (p
[0] | ((word
)p
[1]) << 8);
89 smb_encode_smb_length (byte
* p
, dword len
)
91 /* 0x00 = NetBIOS session message */
97 /* Payload length in network byte order. */
98 p
[2] = (len
& 0xFF00) >> 8;
101 /* Length is actually a 17 bit integer. */
102 p
[1] |= (len
>> 16) & 1;
108 smb_encode_dialect (byte
* p
, const byte
* name
, int len
)
117 smb_encode_ascii (byte
* p
, const byte
* name
, int len
)
126 smb_encode_vblock (byte
* p
, const byte
* data
, word len
, int unused_fs
)
129 p
= smb_encode_word (p
, len
);
130 memcpy (p
, data
, len
);
134 smb_decode_data (const byte
* p
, byte
* data
, word
* data_len
, int unused_fs
)
138 if (!((*p
) == 1 || (*p
) == 5))
139 LOG (("Warning! Data block not starting with 1 or 5\n"));
144 memcpy (data
, p
, len
);
148 return (byte
*)p
+ len
;
152 smb_name_mangle (byte
* p
, const byte
* name
)
161 (*p
++) = 2 * (len
+ pad
);
163 while ((*name
) != '\0')
165 (*p
++) = ((*name
) >> 4) + 'A';
166 (*p
++) = ((*name
) & 0x0F) + 'A';
182 /* According to the core protocol documentation times are
183 expressed as seconds past January 1st, 1970, local
186 utc2local (int time_value
)
191 result
= time_value
- GetTimeZoneDelta();
199 local2utc (int time_value
)
204 result
= time_value
+ GetTimeZoneDelta();
211 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since January 1st 1970). */
213 date_dos2unix (unsigned short time_value
, unsigned short date
)
218 memset(&tm
,0,sizeof(tm
));
220 tm
.tm_sec
= 2 * (time_value
& 0x1F);
221 tm
.tm_min
= (time_value
>> 5) & 0x3F;
222 tm
.tm_hour
= (time_value
>> 11) & 0x1F;
223 tm
.tm_mday
= date
& 0x1F;
224 tm
.tm_mon
= ((date
>> 5) & 0xF) - 1;
225 tm
.tm_year
= ((date
>> 9) & 0x7F) + 80;
227 seconds
= MakeTime(&tm
);
232 /* Convert linear UNIX date to a MS-DOS time/date pair. */
234 date_unix2dos (int unix_date
, unsigned short *time_value
, unsigned short *date
)
238 GMTime(unix_date
,&tm
);
240 (*time_value
) = (tm
.tm_hour
<< 11) | (tm
.tm_min
<< 5) | (tm
.tm_sec
/ 2);
241 (*date
) = ((tm
.tm_year
- 80) << 9) | ((tm
.tm_mon
+ 1) << 5) | tm
.tm_mday
;
244 /****************************************************************************
248 ****************************************************************************/
250 smb_len (const byte
* packet
)
252 /* This returns the payload length stored in the NetBIOS session header. */
253 return (dword
)( (((dword
)(packet
[1] & 0x1)) << 16) | (((dword
)packet
[2]) << 8) | (packet
[3]) );
257 smb_bcc (const byte
* packet
)
259 int pos
= SMB_HEADER_LEN
+ SMB_WCT (packet
) * sizeof (word
);
261 return (word
)(packet
[pos
] | ((word
)packet
[pos
+ 1]) << 8);
264 /* smb_valid_packet: We check if packet fulfills the basic
265 requirements of a smb packet */
267 smb_valid_packet (const byte
* packet
)
271 LOG (("len: %ld, wct: %ld, bcc: %ld -- SMB_HEADER_LEN[%ld] + SMB_WCT (packet) * 2[%ld] + SMB_BCC (packet)[%ld] + 2 = %ld\n",
276 SMB_WCT (packet
) * 2,
278 SMB_HEADER_LEN
+ SMB_WCT (packet
) * 2 + SMB_BCC (packet
) + 2));
280 /* olsen: During protocol negotiation Samba 3.2.5 may return SMB responses which contain
281 more data than is called for. I'm not sure what the right approach to handle
282 this would be. But for now, I've modified this test to check only if there
283 is less data in a response than required. */
284 result
= (packet
[4] == 0xff
288 && (smb_len (packet
) + 4 >= (dword
)
289 (SMB_HEADER_LEN
+ SMB_WCT (packet
) * 2 + SMB_BCC (packet
) + 2))) ? 0 : (-EIO
);
294 /* smb_verify: We check if we got the answer we expected, and if we
295 got enough data. If bcc == -1, we don't care. */
297 smb_verify (const byte
* packet
, int command
, int wct
, int bcc
)
299 return (SMB_CMD (packet
) == command
&&
300 SMB_WCT (packet
) >= wct
&&
301 (bcc
== -1 || SMB_BCC (packet
) >= bcc
)) ? 0 : -EIO
;
305 smb_errno (int errcls
, int error
)
310 smb_printerr (errcls
, error
);
312 if (errcls
== ERRDOS
)
314 static const int map
[][2] =
316 { ERRbadfunc
,EINVAL
},
317 { ERRbadfile
,ENOENT
},
318 { ERRbadpath
,ENOENT
},
319 { ERRnofids
,EMFILE
},
320 { ERRnoaccess
,EACCES
},
324 { ERRbadmem
,EFAULT
},
326 { ERRbadformat
,EIO
},
327 { ERRbadaccess
,EACCES
},
328 { ERRbaddata
,E2BIG
},
329 { ERRbaddrive
,ENXIO
},
331 { ERRdiffdevice
,EXDEV
},
333 { ERRbadshare
,ETXTBSY
},
335 { ERRfilexists
,EEXIST
},
336 { 87,0 },/* Unknown error! */
337 { 183,EEXIST
},/* This next error seems to occur on an mv when the destination exists */
343 for(i
= 0 ; map
[i
][0] != -1 ; i
++)
345 if(map
[i
][0] == error
)
352 else if (errcls
== ERRSRV
)
354 static const int map
[][2] =
359 { ERRaccess
,EACCES
},
365 for(i
= 0 ; map
[i
][0] != -1 ; i
++)
367 if(map
[i
][0] == error
)
374 else if (errcls
== ERRHRD
)
376 static const int map
[][2] =
378 { ERRnowrite
,EROFS
},
379 { ERRbadunit
,ENODEV
},
380 { ERRnotready
,EBUSY
},
383 { ERRbadreq
,ERANGE
},
384 { ERRbadshare
,ETXTBSY
},
391 for(i
= 0 ; map
[i
][0] != -1 ; i
++)
393 if(map
[i
][0] == error
)
400 else if (errcls
== ERRCMD
)
417 if ((c
< ' ') || (c
> '~'))
424 smb_dump_packet (byte
* packet
)
429 errcls
= (int) packet
[9];
430 error
= (int) (int) (packet
[11] | ((int)packet
[12]) << 8);
432 LOG (("smb_len = %ld valid = %ld\n", len
= smb_len (packet
), smb_valid_packet (packet
)));
433 LOG (("smb_cmd = %ld smb_wct = %ld smb_bcc = %ld\n", packet
[8], SMB_WCT (packet
), SMB_BCC (packet
)));
434 LOG (("smb_rcls = %ld smb_err = %ld\n", errcls
, error
));
437 smb_printerr (errcls
, error
);
444 for (i
= 0; i
< len
; i
+= 10)
446 PRINTF (("%03ld:", i
));
448 for (j
= i
; j
< i
+ 10; j
++)
451 PRINTF (("%02lx ", packet
[j
]));
458 for (j
= i
; j
< i
+ 10; j
++)
461 PRINTF (("%lc", print_char (packet
[j
])));
470 /* smb_request_ok: We expect the server to be locked. Then we do the
471 request and check the answer completely. When smb_request_ok
472 returns 0, you can be quite sure that everything went well. When
473 the answer is <=0, the returned number is a valid unix errno. */
475 smb_request_ok (struct smb_server
*s
, int command
, int wct
, int bcc
)
483 result
= smb_request (s
);
486 LOG (("smb_request failed\n"));
488 else if ((error
= smb_valid_packet (s
->packet
)) != 0)
490 LOG (("not a valid packet!\n"));
493 else if (s
->rcls
!= 0)
495 result
= -smb_errno (s
->rcls
, s
->err
);
497 else if ((error
= smb_verify (s
->packet
, command
, wct
, bcc
)) != 0)
499 LOG (("smb_verify failed\n"));
506 /* smb_retry: This function should be called when smb_request_ok has
507 indicated an error. If the error was indicated because the
508 connection was killed, we try to reconnect. If smb_retry returns 0,
509 the error was indicated for another reason, so a retry would not be
512 smb_retry (struct smb_server
*server
)
516 if (server
->state
== CONN_VALID
)
519 if (smb_release (server
) < 0)
521 LOG (("smb_retry: smb_release failed\n"));
522 server
->state
= CONN_RETRIED
;
526 if (smb_proc_reconnect (server
) < 0)
528 LOG (("smb_proc_reconnect failed\n"));
529 server
->state
= CONN_RETRIED
;
533 server
->state
= CONN_VALID
;
542 smb_request_ok_unlock (struct smb_server
*s
, int command
, int wct
, int bcc
)
546 result
= smb_request_ok (s
, command
, wct
, bcc
);
551 /* smb_setup_header: We completely set up the packet. You only have to
552 insert the command-specific fields */
554 smb_setup_header (struct smb_server
*server
, byte command
, word wct
, word bcc
)
556 dword xmit_len
= SMB_HEADER_LEN
+ wct
* sizeof (word
) + bcc
+ 2;
557 byte
*p
= server
->packet
;
558 byte
*buf
= server
->packet
;
560 /* This sets up the NetBIOS session header. 'xmit_length'
561 * is the amount of data that follows the header.
563 p
= smb_encode_smb_length (p
, xmit_len
);
569 BSET (p
, 4, command
);
571 /* Fixed header length (32 bytes). */
572 memset (&p
[5], 0, 32 - 5);
576 WSET (buf
, smb_tid
, server
->tid
);
577 WSET (buf
, smb_pid
, 0); /* server->pid */
578 WSET (buf
, smb_uid
, server
->server_uid
);
579 WSET (buf
, smb_mid
, 0); /* server->mid */
581 if (server
->protocol
> PROTOCOL_CORE
)
583 BSET (buf
, smb_flg
, 0x8); /* path names are caseless */
584 WSET (buf
, smb_flg2
, 0x3); /* extended attributes supported, long names supported */
594 /* smb_setup_header_exclusive waits on server->lock and locks the
595 server, when it's free. You have to unlock it manually when you're
596 finished with server->packet! */
598 smb_setup_header_exclusive (struct smb_server
*server
, byte command
, word wct
, word bcc
)
602 result
= smb_setup_header (server
, command
, wct
, bcc
);
607 /*****************************************************************************
609 * File operation section.
611 ****************************************************************************/
614 smb_proc_open (struct smb_server
*server
, const char *pathname
, int len
, struct smb_dirent
*entry
)
618 char *buf
= server
->packet
;
619 const word o_attr
= aSYSTEM
| aHIDDEN
| aDIR
;
621 LOG (("path=%s\n", pathname
));
625 p
= smb_setup_header (server
, SMBopen
, 2, 2 + len
);
626 WSET (buf
, smb_vwv0
, 0x42); /* read/write */
627 WSET (buf
, smb_vwv1
, o_attr
);
628 smb_encode_ascii (p
, pathname
, len
);
630 if ((error
= smb_request_ok (server
, SMBopen
, 7, 0)) < 0)
632 if (smb_retry (server
))
635 if (error
!= -EACCES
)
638 p
= smb_setup_header (server
, SMBopen
, 2, 2 + len
);
639 WSET (buf
, smb_vwv0
, 0x40); /* read only */
640 WSET (buf
, smb_vwv1
, o_attr
);
641 smb_encode_ascii (p
, pathname
, len
);
643 if ((error
= smb_request_ok (server
, SMBopen
, 7, 0)) < 0)
645 if (smb_retry (server
))
652 /* We should now have data in vwv[0..6]. */
653 entry
->fileid
= WVAL (buf
, smb_vwv0
);
654 entry
->attr
= WVAL (buf
, smb_vwv1
);
655 entry
->ctime
= entry
->atime
= entry
->mtime
= entry
->wtime
= local2utc (DVAL (buf
, smb_vwv2
));
656 entry
->size
= DVAL (buf
, smb_vwv4
);
663 GMTime(entry
->ctime
,&tm
);
664 LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
666 GMTime(entry
->atime
,&tm
);
667 LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
669 GMTime(entry
->mtime
,&tm
);
670 LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
672 GMTime(entry
->wtime
,&tm
);
673 LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
682 /* smb_proc_close: in finfo->mtime we can send a modification time to
685 smb_proc_close (struct smb_server
*server
, word fileid
, dword mtime
)
687 char *buf
= server
->packet
;
691 if(mtime
!= 0 && mtime
!= 0xffffffff)
693 /* 0 and 0xffffffff mean: do not set mtime */
694 local_time
= utc2local (mtime
);
701 smb_setup_header_exclusive (server
, SMBclose
, 3, 0);
702 WSET (buf
, smb_vwv0
, fileid
);
703 DSET (buf
, smb_vwv1
, local_time
);
705 result
= smb_request_ok_unlock (server
, SMBclose
, 0, 0);
710 /* In smb_proc_read and smb_proc_write we do not retry, because the
711 file-id would not be valid after a reconnection. */
713 /* smb_proc_read: fs indicates if it should be copied with
716 smb_proc_read (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, long count
, char *data
, int fs
)
718 word returned_count
, data_len
;
719 char *buf
= server
->packet
;
723 smb_setup_header_exclusive (server
, SMBread
, 5, 0);
725 WSET (buf
, smb_vwv0
, finfo
->fileid
);
726 WSET (buf
, smb_vwv1
, count
);
727 DSET (buf
, smb_vwv2
, offset
);
728 WSET (buf
, smb_vwv4
, 0);
730 if ((error
= smb_request_ok (server
, SMBread
, 5, -1)) < 0)
736 returned_count
= WVAL (buf
, smb_vwv0
);
738 smb_decode_data (SMB_BUF (server
->packet
), data
, &data_len
, fs
);
740 if (returned_count
!= data_len
)
742 LOG (("Warning, returned_count != data_len\n"));
743 LOG (("ret_c=%ld, data_len=%ld\n", returned_count
, data_len
));
747 LOG (("ret_c=%ld, data_len=%ld\n", returned_count
, data_len
));
757 /* count must be <= 65535. No error number is returned. A result of 0
758 indicates an error, which has to be investigated by a normal read
761 smb_proc_read_raw (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, long count
, char *data
)
763 char *buf
= server
->packet
;
766 smb_setup_header_exclusive (server
, SMBreadbraw
, 8, 0);
768 WSET (buf
, smb_vwv0
, finfo
->fileid
);
769 DSET (buf
, smb_vwv1
, offset
);
770 WSET (buf
, smb_vwv3
, count
); /* maxcnt */
771 WSET (buf
, smb_vwv4
, 0); /* mincnt */
772 DSET (buf
, smb_vwv5
, 0); /* timeout */
773 WSET (buf
, smb_vwv7
, 0); /* reserved */
775 result
= smb_request_read_raw (server
, data
, count
);
781 smb_proc_write (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, long count
, const char *data
)
784 char *buf
= server
->packet
;
787 p
= smb_setup_header_exclusive (server
, SMBwrite
, 5, count
+ 3);
788 WSET (buf
, smb_vwv0
, finfo
->fileid
);
789 WSET (buf
, smb_vwv1
, count
);
790 DSET (buf
, smb_vwv2
, offset
);
791 WSET (buf
, smb_vwv4
, 0);
795 memcpy (p
+ 2, data
, count
);
797 if ((res
= smb_request_ok (server
, SMBwrite
, 1, 0)) >= 0)
798 res
= WVAL (buf
, smb_vwv0
);
803 /* count must be <= 65535 */
805 smb_proc_write_raw (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, long count
, const char *data
)
807 char *buf
= server
->packet
;
809 long len
= server
->max_buffer_size
- 4;
815 len
= count
- len
; /* transfer the larger part using the second packet */
817 p
= smb_setup_header_exclusive (server
, SMBwritebraw
, server
->protocol
> PROTOCOL_COREPLUS
? 12 : 11, len
);
819 WSET (buf
, smb_vwv0
, finfo
->fileid
);
820 DSET (buf
, smb_vwv1
, count
);
821 DSET (buf
, smb_vwv3
, offset
);
822 DSET (buf
, smb_vwv5
, 0); /* timeout */
823 WSET (buf
, smb_vwv7
, 1); /* send final result response */
824 DSET (buf
, smb_vwv8
, 0); /* reserved */
826 if (server
->protocol
> PROTOCOL_COREPLUS
)
828 WSET (buf
, smb_vwv10
, len
);
829 WSET (buf
, smb_vwv11
, p
- smb_base(buf
));
833 WSET (buf
, smb_vwv10
, 0);
837 memcpy (p
, data
, len
);
839 result
= smb_request_ok (server
, SMBwritebraw
, 1, 0);
841 LOG (("first request returned %ld\n", result
));
846 result
= smb_request_write_raw (server
, data
+ len
, count
- len
);
848 LOG(("raw request returned %ld\n", result
));
854 /* We have to do the checks of smb_request_ok here as well */
855 if ((error
= smb_valid_packet (server
->packet
)) != 0)
857 LOG (("not a valid packet!\n"));
860 else if (server
->rcls
!= 0)
862 result
= -smb_errno (server
->rcls
, server
->err
);
866 int sock_fd
= server
->mount_data
.fd
;
868 /* SMBwritebraw may be followed by the server sending
869 * several interim update responses of SMBwritebraw,
870 * which are eventually followed by a final response
871 * of SMBwritec (complete).
873 while(SMB_CMD(server
->packet
) == SMBwritebraw
&& SMB_BCC(server
->packet
) == 0 && SMB_WCT(server
->packet
) == 1)
875 error
= smb_receive (server
, sock_fd
);
882 error
= smb_valid_packet (server
->packet
);
889 if (server
->rcls
!= 0)
891 result
= -smb_errno (server
->rcls
, server
->err
);
896 /* If everything went fine so far, this should be the
897 * final packet which concludes the transfer.
901 error
= smb_verify (server
->packet
, SMBwritec
, 1, 0);
904 LOG (("smb_verify failed\n"));
910 /* If everything went fine, the whole block has been transfered. */
911 if (result
== (count
- len
))
921 smb_proc_lseek (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, int mode
, off_t
* new_position_ptr
)
923 char *buf
= server
->packet
;
928 smb_setup_header (server
, SMBlseek
, 4,0);
930 WSET (buf
, smb_vwv0
, finfo
->fileid
);
931 WSET (buf
, smb_vwv1
, mode
);
932 DSET (buf
, smb_vwv2
, offset
);
934 if ((error
= smb_request_ok (server
, SMBlseek
, 1, 0)) < 0)
936 if (smb_retry (server
))
941 (*new_position_ptr
) = DVAL(buf
, smb_vwv0
);
947 /* smb_proc_lockingX: We don't chain any further packets to the initial one */
949 smb_proc_lockingX (struct smb_server
*server
, struct smb_dirent
*finfo
, struct smb_lkrng
*locks
, int num_entries
, int mode
, long timeout
)
952 int num_locks
, num_unlocks
;
953 char *buf
= server
->packet
;
958 num_locks
= num_unlocks
= 0;
961 num_unlocks
= num_entries
;
963 num_locks
= num_entries
;
967 data
= smb_setup_header(server
, SMBlockingX
, 8, num_entries
* 10);
969 BSET (buf
, smb_vwv0
, 0xFF);
970 WSET (buf
, smb_vwv1
, 0);
971 WSET (buf
, smb_vwv2
, finfo
->fileid
);
972 WSET (buf
, smb_vwv3
, mode
& 1); /* must be WSET() or new oplock level will be random */
973 DSET (buf
, smb_vwv4
, timeout
);
974 WSET (buf
, smb_vwv6
, num_unlocks
);
975 WSET (buf
, smb_vwv7
, num_locks
);
977 for (i
= 0, p
= locks
; i
< num_entries
; i
++, p
++)
979 WSET (data
, SMB_LPID_OFFSET(i
), 0); /* server->pid */
980 DSET (data
, SMB_LKOFF_OFFSET(i
), p
->offset
);
981 DSET (data
, SMB_LKLEN_OFFSET(i
), p
->len
);
984 if ((result
= smb_request_ok (server
, SMBlockingX
, 0, 0)) < 0)
986 if (smb_retry (server
))
993 /* smb_proc_do_create: We expect entry->attry & entry->ctime to be set. */
995 smb_proc_do_create (struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*entry
, word command
)
999 char *buf
= server
->packet
;
1004 p
= smb_setup_header (server
, command
, 3, len
+ 2);
1005 WSET (buf
, smb_vwv0
, entry
->attr
);
1006 local_time
= utc2local (entry
->ctime
);
1007 DSET (buf
, smb_vwv1
, local_time
);
1008 smb_encode_ascii (p
, path
, len
);
1010 if ((error
= smb_request_ok (server
, command
, 1, 0)) < 0)
1012 if (smb_retry (server
))
1019 entry
->fileid
= WVAL (buf
, smb_vwv0
);
1021 smb_proc_close (server
, entry
->fileid
, entry
->mtime
);
1029 smb_proc_create (struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*entry
)
1031 return smb_proc_do_create (server
, path
, len
, entry
, SMBcreate
);
1035 smb_proc_mv (struct smb_server
*server
, const char *opath
, const int olen
, const char *npath
, const int nlen
)
1038 char *buf
= server
->packet
;
1043 p
= smb_setup_header (server
, SMBmv
, 1, olen
+ nlen
+ 4);
1045 WSET (buf
, smb_vwv0
, 0);
1047 p
= smb_encode_ascii (p
, opath
, olen
);
1048 smb_encode_ascii (p
, npath
, olen
);
1050 if ((result
= smb_request_ok (server
, SMBmv
, 0, 0)) < 0)
1052 if (smb_retry (server
))
1060 smb_proc_mkdir (struct smb_server
*server
, const char *path
, const int len
)
1067 p
= smb_setup_header (server
, SMBmkdir
, 0, 2 + len
);
1069 smb_encode_ascii (p
, path
, len
);
1071 if ((result
= smb_request_ok (server
, SMBmkdir
, 0, 0)) < 0)
1073 if (smb_retry (server
))
1081 smb_proc_rmdir (struct smb_server
*server
, const char *path
, const int len
)
1088 p
= smb_setup_header (server
, SMBrmdir
, 0, 2 + len
);
1090 smb_encode_ascii (p
, path
, len
);
1092 if ((result
= smb_request_ok (server
, SMBrmdir
, 0, 0)) < 0)
1094 if (smb_retry (server
))
1102 smb_proc_unlink (struct smb_server
*server
, const char *path
, const int len
)
1105 char *buf
= server
->packet
;
1110 p
= smb_setup_header (server
, SMBunlink
, 1, 2 + len
);
1112 WSET (buf
, smb_vwv0
, 0);
1114 smb_encode_ascii (p
, path
, len
);
1116 if ((result
= smb_request_ok (server
, SMBunlink
, 0, 0)) < 0)
1118 if (smb_retry (server
))
1126 smb_proc_trunc (struct smb_server
*server
, word fid
, dword length
)
1129 char *buf
= server
->packet
;
1132 p
= smb_setup_header (server
, SMBwrite
, 5, 3);
1133 WSET (buf
, smb_vwv0
, fid
);
1134 WSET (buf
, smb_vwv1
, 0);
1135 DSET (buf
, smb_vwv2
, length
);
1136 WSET (buf
, smb_vwv4
, 0);
1137 smb_encode_ascii (p
, "", 0);
1139 result
= smb_request_ok (server
, SMBwrite
, 1, 0);
1141 result
= DVAL(buf
, smb_vwv0
);
1147 smb_decode_dirent (char *p
, struct smb_dirent
*entry
)
1151 p
+= SMB_STATUS_SIZE
; /* reserved (search_status) */
1153 entry
->attr
= BVAL (p
, 0);
1154 entry
->mtime
= entry
->atime
= entry
->ctime
= entry
->wtime
= date_dos2unix (WVAL (p
, 1), WVAL (p
, 3));
1155 entry
->size
= DVAL (p
, 5);
1159 if(name_size
> entry
->complete_path_size
-1)
1160 name_size
= entry
->complete_path_size
-1;
1162 memcpy (entry
->complete_path
, p
+ 9, name_size
);
1164 entry
->complete_path
[name_size
] = '\0';
1166 LOG (("smb_decode_dirent: path = %s\n", entry
->complete_path
));
1172 GMTime(entry
->ctime
,&tm
);
1173 LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1175 GMTime(entry
->atime
,&tm
);
1176 LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1178 GMTime(entry
->mtime
,&tm
);
1179 LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1181 GMTime(entry
->wtime
,&tm
);
1182 LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1189 /* This routine is used to read in directory entries from the network.
1190 Note that it is for short directory name seeks, i.e.: protocol < PROTOCOL_LANMAN2 */
1192 smb_proc_readdir_short (struct smb_server
*server
, char *path
, int fpos
, int cache_size
, struct smb_dirent
*entry
)
1199 int first
, total_count
;
1200 struct smb_dirent
*current_entry
;
1203 char status
[SMB_STATUS_SIZE
];
1204 int entries_asked
= (server
->max_buffer_size
- 100) / SMB_DIRINFO_SIZE
;
1205 int dirlen
= strlen (path
);
1208 mask
= malloc(dirlen
+ 4 + 1);
1215 strcpy (mask
, path
);
1216 strcat (mask
, "\\*.*");
1218 LOG (("SMB call readdir %ld @ %ld\n", cache_size
, fpos
));
1219 LOG ((" mask = %s\n", mask
));
1221 buf
= server
->packet
;
1227 current_entry
= entry
;
1233 p
= smb_setup_header (server
, SMBsearch
, 2, 5 + strlen (mask
));
1234 WSET (buf
, smb_vwv0
, entries_asked
);
1235 WSET (buf
, smb_vwv1
, aDIR
);
1236 p
= smb_encode_ascii (p
, mask
, strlen (mask
));
1238 (void) smb_encode_word (p
, 0);
1242 p
= smb_setup_header (server
, SMBsearch
, 2, 5 + SMB_STATUS_SIZE
);
1243 WSET (buf
, smb_vwv0
, entries_asked
);
1244 WSET (buf
, smb_vwv1
, aDIR
);
1245 p
= smb_encode_ascii (p
, "", 0);
1246 (void) smb_encode_vblock (p
, status
, SMB_STATUS_SIZE
, 0);
1249 if ((error
= smb_request_ok (server
, SMBsearch
, 1, -1)) < 0)
1251 if ((server
->rcls
== ERRDOS
) && (server
->err
== ERRnofiles
))
1253 result
= total_count
- fpos
;
1258 if (smb_retry (server
))
1267 p
= SMB_VWV (server
->packet
);
1268 p
= smb_decode_word (p
, &count
); /* vwv[0] = count-returned */
1269 p
= smb_decode_word (p
, &bcc
);
1275 result
= total_count
- fpos
;
1280 if (bcc
!= count
* SMB_DIRINFO_SIZE
+ 3)
1287 p
+= 3; /* Skipping VBLOCK header (5, length lo, length hi). */
1289 /* Read the last entry into the status field. */
1290 memcpy (status
, SMB_BUF (server
->packet
) + 3 + (count
- 1) * SMB_DIRINFO_SIZE
, SMB_STATUS_SIZE
);
1292 /* Now we are ready to parse smb directory entries. */
1294 for (i
= 0; i
< count
; i
++)
1296 if (total_count
< fpos
)
1298 p
+= SMB_DIRINFO_SIZE
;
1300 LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n", total_count
, i
, fpos
));
1302 else if (total_count
>= fpos
+ cache_size
)
1304 result
= total_count
- fpos
;
1310 p
= smb_decode_dirent (p
, current_entry
);
1329 /*****************************************************************************/
1331 #if !defined(__AROS__)
1332 /* Interpret an 8 byte "filetime" structure to a 'time_t'.
1333 * It's originally in "100ns units since jan 1st 1601".
1335 * Unlike the Samba implementation of that date conversion
1336 * algorithm this one tries to perform the entire
1337 * calculation using integer operations only.
1340 interpret_long_date(char * p
)
1347 /* Extract the 64 bit time value. */
1348 long_date
.Low
= DVAL(p
,0);
1349 long_date
.High
= DVAL(p
,4);
1351 /* Divide by 10,000,000 to convert the time from 100ns
1352 units into seconds. */
1353 divide_64_by_32(&long_date
,10000000,&long_date
);
1355 /* Adjust by 369 years (11,644,473,600 seconds) to convert
1356 from the epoch beginning on January 1st 1601 to the one
1357 beginning on January 1st 1970 (the Unix epoch). */
1358 adjust
.Low
= 0xb6109100;
1359 adjust
.High
= 0x00000002;
1361 underflow
= subtract_64_from_64_to_64(&long_date
,&adjust
,&long_date
);
1363 /* If the result did not produce an underflow or overflow,
1364 return the number of seconds encoded in the least
1365 significant word of the result. */
1366 if(underflow
== 0 && long_date
.High
== 0)
1367 result
= long_date
.Low
;
1375 interpret_long_date(char * p
)
1380 long_date
= *(UQUAD
*)p
- (0x2B6109100ULL
* 10000000);
1381 sectime
= long_date
/ 10000000;
1383 return((time_t)sectime
);
1387 /*****************************************************************************/
1390 smb_get_dirent_name(char *p
,int level
,char ** name_ptr
,int * len_ptr
)
1394 case 1: /* OS/2 understands this */
1395 (*name_ptr
) = p
+ 27;
1396 (*len_ptr
) = strlen(p
+ 27);
1399 case 2: /* this is what OS/2 uses */
1400 (*name_ptr
) = p
+ 31;
1401 (*len_ptr
) = strlen(p
+ 31);
1404 case 3: /* untested */
1405 (*name_ptr
) = p
+ 33;
1406 (*len_ptr
) = strlen(p
+ 33);
1409 case 4: /* untested */
1410 (*name_ptr
) = p
+ 37;
1411 (*len_ptr
) = strlen(p
+ 37);
1414 case 260: /* NT uses this, but also accepts 2 */
1415 (*name_ptr
) = p
+ 94;
1416 (*len_ptr
) = min (DVAL (p
+60, 0), SMB_MAXNAMELEN
);
1426 /* interpret a long filename structure - this is mostly guesses at the
1427 moment. The length of the structure is returned. The structure of
1428 a long filename depends on the info level. 260 is used by NT and 2
1431 smb_decode_long_dirent (char *p
, struct smb_dirent
*finfo
, int level
)
1437 case 1: /* OS/2 understands this */
1443 memcpy(buffer
,p
+ 27,sizeof(buffer
)-1);
1444 buffer
[sizeof(buffer
)-1] = '\0';
1446 LOG(("type=%ld, name='%s'\n",level
,buffer
));
1452 strlcpy (finfo
->complete_path
, p
+ 27, finfo
->complete_path_size
);
1453 finfo
->len
= strlen (finfo
->complete_path
);
1454 finfo
->size
= DVAL (p
, 16);
1455 finfo
->attr
= BVAL (p
, 24);
1456 finfo
->ctime
= date_dos2unix (WVAL (p
, 6), WVAL (p
, 4));
1457 finfo
->atime
= date_dos2unix (WVAL (p
, 10), WVAL (p
, 8));
1458 finfo
->mtime
= date_dos2unix (WVAL (p
, 14), WVAL (p
, 12));
1459 finfo
->wtime
= finfo
->mtime
;
1465 GMTime(finfo
->ctime
,&tm
);
1466 LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1468 GMTime(finfo
->atime
,&tm
);
1469 LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1471 GMTime(finfo
->mtime
,&tm
);
1472 LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1474 GMTime(finfo
->wtime
,&tm
);
1475 LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1480 result
= p
+ 28 + BVAL (p
, 26);
1484 case 2: /* this is what OS/2 uses */
1490 memcpy(buffer
,p
+ 31,sizeof(buffer
)-1);
1491 buffer
[sizeof(buffer
)-1] = '\0';
1493 LOG(("type=%ld, name='%s'\n",level
,buffer
));
1499 strlcpy (finfo
->complete_path
, p
+ 31, finfo
->complete_path_size
);
1500 finfo
->len
= strlen (finfo
->complete_path
);
1501 finfo
->size
= DVAL (p
, 16);
1502 finfo
->attr
= BVAL (p
, 24);
1503 finfo
->ctime
= date_dos2unix (WVAL (p
, 6), WVAL (p
, 4));
1504 finfo
->atime
= date_dos2unix (WVAL (p
, 10), WVAL (p
, 8));
1505 finfo
->mtime
= date_dos2unix (WVAL (p
, 14), WVAL (p
, 12));
1506 finfo
->wtime
= finfo
->mtime
;
1512 GMTime(finfo
->ctime
,&tm
);
1513 LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1515 GMTime(finfo
->atime
,&tm
);
1516 LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1518 GMTime(finfo
->mtime
,&tm
);
1519 LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1521 GMTime(finfo
->wtime
,&tm
);
1522 LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1527 result
= p
+ 32 + BVAL (p
, 30);
1531 case 260: /* NT uses this, but also accepts 2 */
1538 len
= min (DVAL (p
+60, 0), sizeof(buffer
)-1);
1540 memcpy(buffer
,p
+94,len
);
1543 LOG(("type=%ld, name='%s'\n",level
,buffer
));
1547 result
= p
+ WVAL (p
, 0);
1554 p
+= 4; /* next entry offset */
1555 p
+= 4; /* fileindex */
1556 finfo
->ctime
= interpret_long_date(p
);
1558 finfo
->atime
= interpret_long_date(p
);
1560 finfo
->wtime
= interpret_long_date(p
);
1562 finfo
->mtime
= interpret_long_date(p
);
1564 finfo
->size
= DVAL (p
, 0);
1566 p
+= 8; /* alloc size */
1567 finfo
->attr
= BVAL (p
, 0);
1569 namelen
= min (DVAL (p
, 0), SMB_MAXNAMELEN
);
1571 p
+= 4; /* EA size */
1572 p
+= 2; /* short name len? */
1573 p
+= 24; /* short name? */
1575 if(namelen
> (int)finfo
->complete_path_size
-1)
1576 namelen
= finfo
->complete_path_size
-1;
1578 /* If the modification time is not set, try to
1579 substitute the write time for it. */
1580 if(finfo
->mtime
== 0)
1581 finfo
->mtime
= finfo
->wtime
;
1583 /* Swap last modification time and last write time. */
1584 swap
= finfo
->mtime
;
1585 finfo
->mtime
= finfo
->wtime
;
1586 finfo
->wtime
= swap
;
1588 memcpy (finfo
->complete_path
, p
, namelen
);
1589 finfo
->complete_path
[namelen
] = '\0';
1590 finfo
->len
= namelen
;
1596 GMTime(finfo
->ctime
,&tm
);
1597 LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1599 GMTime(finfo
->atime
,&tm
);
1600 LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1602 GMTime(finfo
->wtime
,&tm
);
1603 LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1605 GMTime(finfo
->mtime
,&tm
);
1606 LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
1617 /* I have to set times to 0 here, because I do not
1618 have specs about this for all info levels. */
1619 finfo
->ctime
= finfo
->mtime
= finfo
->wtime
= finfo
->atime
= 0;
1622 LOG (("Unknown long filename format %ld\n", level
));
1624 result
= p
+ WVAL (p
, 0);
1633 smb_proc_readdir_long (struct smb_server
*server
, char *path
, int fpos
, int cache_size
, struct smb_dirent
*entry
)
1635 int max_matches
= 512; /* this should actually be based on the max_buffer_size value */
1637 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1638 int info_level
= server
->protocol
< PROTOCOL_NT1
? 1 : 260;
1643 int total_count
= 0;
1644 struct smb_dirent
*current_entry
;
1648 int resp_data_len
= 0;
1649 int resp_param_len
= 0;
1651 int attribute
= aSYSTEM
| aHIDDEN
| aDIR
;
1657 int ff_dir_handle
= 0;
1658 int ff_resume_key
= 0;
1661 unsigned char *outbuf
= server
->packet
;
1663 int dirlen
= strlen (path
) + 2 + 1;
1669 /* ZZZ experimental 'max_matches' adjustment */
1671 if(info_level == 260)
1672 max_matches = server->max_buffer_size / 360;
1674 max_matches = server->max_buffer_size / 40;
1677 SHOWVALUE(server
->max_buffer_size
);
1678 SHOWVALUE(max_matches
);
1680 mask
= malloc (dirlen
);
1683 LOG (("Memory allocation failed\n"));
1689 strcpy (mask
, path
);
1690 strcat (mask
, "\\*");
1691 masklen
= strlen (mask
);
1693 LOG (("SMB call lreaddir %ld @ %ld\n", cache_size
, fpos
));
1694 LOG ((" mask = %s\n", mask
));
1703 current_entry
= entry
;
1708 if (loop_count
> 200)
1710 LOG (("smb_proc_readdir_long: Looping in FIND_NEXT???\n"));
1716 memset (outbuf
, 0, 39);
1718 smb_setup_header (server
, SMBtrans2
, 15, 5 + 12 + masklen
+ 1);
1720 WSET (outbuf
, smb_tpscnt
, 12 + masklen
+ 1);
1721 WSET (outbuf
, smb_tdscnt
, 0);
1722 WSET (outbuf
, smb_mprcnt
, 10);
1723 WSET (outbuf
, smb_mdrcnt
, server
->max_buffer_size
);
1724 WSET (outbuf
, smb_msrcnt
, 0);
1725 WSET (outbuf
, smb_flags
, 0);
1726 DSET (outbuf
, smb_timeout
, 0);
1727 WSET (outbuf
, smb_pscnt
, WVAL (outbuf
, smb_tpscnt
));
1728 WSET (outbuf
, smb_psoff
, ((SMB_BUF (outbuf
) + 3) - outbuf
) - 4);
1729 WSET (outbuf
, smb_dscnt
, 0);
1730 WSET (outbuf
, smb_dsoff
, 0);
1731 WSET (outbuf
, smb_suwcnt
, 1);
1732 WSET (outbuf
, smb_setup0
, first
== 1 ? TRANSACT2_FINDFIRST
: TRANSACT2_FINDNEXT
);
1734 p
= SMB_BUF (outbuf
);
1735 (*p
++) = 0; /* put in a null smb_name */
1737 (*p
++) = ' '; /* this was added because OS/2 does it */
1741 LOG (("first match\n"));
1742 WSET (p
, 0, attribute
); /* attribute */
1743 WSET (p
, 2, max_matches
); /* max count */
1744 WSET (p
, 4, 8 + 4 + 2); /* resume required + close on end + continue */
1745 WSET (p
, 6, info_level
);
1750 LOG (("next match; ff_dir_handle=0x%lx ff_resume_key=%ld mask='%s'\n", ff_dir_handle
, ff_resume_key
, mask
));
1751 WSET (p
, 0, ff_dir_handle
);
1752 WSET (p
, 2, max_matches
); /* max count */
1753 WSET (p
, 4, info_level
);
1754 DSET (p
, 6, ff_resume_key
);
1755 WSET (p
, 10, 8 + 4 + 2); /* resume required + close on end + continue */
1761 memcpy (p
, mask
, masklen
);
1767 result
= smb_trans2_request (server
, &resp_data_len
, &resp_param_len
, &resp_data
, &resp_param
);
1769 LOG (("smb_proc_readdir_long: smb_trans2_request returns %ld\n", result
));
1773 if (smb_retry (server
))
1776 LOG (("smb_proc_readdir_long: got error from trans2_request\n"));
1782 /* Apparently, there is a bug in Windows 95 and friends which
1783 causes the directory read attempt to fail if you're asking
1784 for too much data too fast... */
1785 if(server
->rcls
== ERRSRV
&& server
->err
== ERRerror
)
1787 SHOWMSG("ouch; delaying and retrying");
1789 Delay(TICKS_PER_SECOND
/ 5);
1794 if (server
->rcls
!= 0)
1796 LOG (("server->rcls = %ld err = %ld\n",server
->rcls
, server
->err
));
1797 error
= smb_errno (server
->rcls
, server
->err
);
1802 /* ZZZ bail out if this is empty. */
1803 if (resp_param
== NULL
)
1806 /* parse out some important return info */
1810 ff_dir_handle
= WVAL (p
, 0);
1811 ff_searchcount
= WVAL (p
, 2);
1812 ff_eos
= WVAL (p
, 4);
1816 ff_searchcount
= WVAL (p
, 0);
1817 ff_eos
= WVAL (p
, 2);
1820 LOG (("received %ld entries (eos=%ld)\n",ff_searchcount
, ff_eos
));
1821 if (ff_searchcount
== 0)
1824 /* ZZZ bail out if this is empty. */
1825 if (resp_data
== NULL
)
1828 /* point to the data bytes */
1831 /* Now we are ready to parse smb directory entries. */
1832 for (i
= 0; i
< ff_searchcount
; i
++)
1834 if(i
== ff_searchcount
- 1)
1839 ff_resume_key
= DVAL(p
, 0);
1841 smb_get_dirent_name(p
,info_level
,&last_name
,&len
);
1846 char buffer
[SMB_MAXNAMELEN
+1];
1848 memcpy(buffer
,last_name
,len
);
1851 LOG(("last name = '%s'\n",buffer
));
1855 if(len
+ 1 > dirlen
)
1857 D(("increasing mask; old value = %ld new value = %ld",dirlen
,len
+1));
1865 mask
= malloc (dirlen
);
1868 LOG (("smb_proc_readdir_long: Memory allocation failed\n"));
1878 memcpy (mask
, last_name
, len
);
1888 if (total_count
< fpos
)
1890 p
= smb_decode_long_dirent (p
, NULL
, info_level
);
1892 LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n",total_count
, i
, fpos
));
1894 else if (total_count
>= fpos
+ cache_size
)
1896 p
= smb_decode_long_dirent (p
, NULL
, info_level
);
1898 LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n",total_count
, i
, fpos
));
1904 p
= smb_decode_long_dirent (p
, current_entry
, info_level
);
1912 SHOWVALUE(ff_resume_key
);
1914 if (resp_data
!= NULL
)
1920 if (resp_param
!= NULL
)
1928 if (ff_searchcount
> 0)
1934 /* finished: not needed any more */
1938 if (resp_data
!= NULL
)
1941 if (resp_param
!= NULL
)
1953 RETURN (total_count
- fpos
);
1954 return (total_count
- fpos
);
1959 smb_proc_readdir (struct smb_server
*server
, char *path
, int fpos
, int cache_size
, struct smb_dirent
*entry
)
1963 if (server
->protocol
>= PROTOCOL_LANMAN2
)
1964 result
= smb_proc_readdir_long (server
, path
, fpos
, cache_size
, entry
);
1966 result
= smb_proc_readdir_short (server
, path
, fpos
, cache_size
, entry
);
1972 smb_proc_getattr_core (struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*entry
)
1976 char *buf
= server
->packet
;
1978 LOG (("smb_proc_getattr: %s\n", path
));
1982 p
= smb_setup_header (server
, SMBgetatr
, 0, 2 + len
);
1983 smb_encode_ascii (p
, path
, len
);
1985 if ((result
= smb_request_ok (server
, SMBgetatr
, 10, 0)) < 0)
1987 if (smb_retry (server
))
1993 entry
->attr
= WVAL (buf
, smb_vwv0
);
1995 /* The server only tells us 1 time */
1996 entry
->ctime
= entry
->atime
= entry
->mtime
= entry
->wtime
= local2utc (DVAL (buf
, smb_vwv1
));
1998 entry
->size
= DVAL (buf
, smb_vwv3
);
2004 GMTime(entry
->ctime
,&tm
);
2005 LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
2007 GMTime(entry
->atime
,&tm
);
2008 LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
2010 GMTime(entry
->mtime
,&tm
);
2011 LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
2013 GMTime(entry
->wtime
,&tm
);
2014 LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
2023 /* smb_proc_getattrE: entry->fid must be valid */
2025 smb_proc_getattrE (struct smb_server
*server
, struct smb_dirent
*entry
)
2027 char *buf
= server
->packet
;
2030 smb_setup_header_exclusive (server
, SMBgetattrE
, 1, 0);
2031 WSET (buf
, smb_vwv0
, entry
->fileid
);
2033 if ((result
= smb_request_ok (server
, SMBgetattrE
, 11, 0)) < 0)
2036 entry
->ctime
= date_dos2unix (WVAL (buf
, smb_vwv1
), WVAL (buf
, smb_vwv0
));
2037 entry
->atime
= date_dos2unix (WVAL (buf
, smb_vwv3
), WVAL (buf
, smb_vwv2
));
2038 entry
->mtime
= date_dos2unix (WVAL (buf
, smb_vwv5
), WVAL (buf
, smb_vwv4
));
2039 entry
->wtime
= entry
->mtime
;
2040 entry
->size
= DVAL (buf
, smb_vwv6
);
2041 entry
->attr
= WVAL (buf
, smb_vwv10
);
2047 GMTime(entry
->ctime
,&tm
);
2048 LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
2050 GMTime(entry
->atime
,&tm
);
2051 LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
2053 GMTime(entry
->mtime
,&tm
);
2054 LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
2056 GMTime(entry
->wtime
,&tm
);
2057 LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm
.tm_year
+ 1900,tm
.tm_mon
+1,tm
.tm_mday
,tm
.tm_hour
,tm
.tm_min
,tm
.tm_sec
));
2066 /* In core protocol, there is only 1 time to be set, we use
2067 entry->mtime, to make touch work. */
2069 smb_proc_setattr_core (struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*new_finfo
)
2072 char *buf
= server
->packet
;
2078 LOG (("smb_proc_setattr_core\n"));
2080 p
= smb_setup_header (server
, SMBsetatr
, 8, 4 + len
);
2081 WSET (buf
, smb_vwv0
, new_finfo
->attr
);
2082 local_time
= utc2local (new_finfo
->mtime
);
2083 DSET (buf
, smb_vwv1
, local_time
);
2084 p
= smb_encode_ascii (p
, path
, len
);
2085 (void) smb_encode_ascii (p
, "", 0);
2087 if ((result
= smb_request_ok (server
, SMBsetatr
, 0, 0)) < 0)
2089 if (smb_retry (server
))
2096 /* smb_proc_setattrE: we do not retry here, because we rely on fid,
2097 which would not be valid after a retry. */
2099 smb_proc_setattrE (struct smb_server
*server
, word fid
, struct smb_dirent
*new_entry
)
2101 char *buf
= server
->packet
;
2102 word date
, time_value
;
2105 LOG (("smb_proc_setattrE\n"));
2107 smb_setup_header_exclusive (server
, SMBsetattrE
, 7, 0);
2109 WSET (buf
, smb_vwv0
, fid
);
2111 date_unix2dos (new_entry
->ctime
, &time_value
, &date
);
2112 WSET (buf
, smb_vwv1
, date
);
2113 WSET (buf
, smb_vwv2
, time_value
);
2115 date_unix2dos (new_entry
->atime
, &time_value
, &date
);
2116 WSET (buf
, smb_vwv3
, date
);
2117 WSET (buf
, smb_vwv4
, time_value
);
2119 date_unix2dos (new_entry
->mtime
, &time_value
, &date
);
2120 WSET (buf
, smb_vwv5
, date
);
2121 WSET (buf
, smb_vwv6
, time_value
);
2123 result
= smb_request_ok_unlock (server
, SMBsetattrE
, 0, 0);
2129 smb_proc_dskattr (struct smb_server
*server
, struct smb_dskattr
*attr
)
2136 smb_setup_header (server
, SMBdskattr
, 0, 0);
2138 if ((error
= smb_request_ok (server
, SMBdskattr
, 5, 0)) < 0)
2140 if (smb_retry (server
))
2146 p
= SMB_VWV (server
->packet
);
2147 p
= smb_decode_word (p
, &attr
->total
);
2148 p
= smb_decode_word (p
, &attr
->allocblocks
);
2149 p
= smb_decode_word (p
, &attr
->blocksize
);
2150 (void) smb_decode_word (p
, &attr
->free
);
2157 /*****************************************************************************
2159 * Mount/umount operations.
2161 ****************************************************************************/
2164 enum smb_protocol prot
;
2168 /* smb_proc_reconnect: We expect the server to be locked, so that you
2169 can call the routine from within smb_retry. The socket must be
2170 created, like after a user-level socket()-call. It may not be
2173 smb_proc_reconnect (struct smb_server
*server
)
2175 static const struct smb_prots prots
[] =
2177 {PROTOCOL_CORE
, "PC NETWORK PROGRAM 1.0"}, /* Core Protocol */
2178 {PROTOCOL_COREPLUS
, "MICROSOFT NETWORKS 1.03"}, /* CorePlus */
2179 {PROTOCOL_LANMAN1
, "MICROSOFT NETWORKS 3.0"}, /* DOS LAN Manager 1.0 */
2180 {PROTOCOL_LANMAN1
, "LANMAN1.0"}, /* LAN Manager 1.0 */
2181 {PROTOCOL_LANMAN2
, "LM1.2X002"}, /* LAN Manager 2.0 */
2182 {PROTOCOL_NT1
, "NT LM 0.12"}, /* NT LAN Manager */
2183 {PROTOCOL_NT1
, "NT LANMAN 1.0"},
2186 const int num_prots
= sizeof(prots
) / sizeof(prots
[0]);
2187 const char dev
[] = "A:";
2189 const int default_max_buffer_size
= 1024; /* Space needed for first request. */
2190 int given_max_xmit
= server
->mount_data
.given_max_xmit
;
2194 unsigned char password
[24];
2196 unsigned char nt_password
[24];
2197 int nt_password_len
;
2198 unsigned char full_share
[SMB_MAXNAMELEN
+1];
2201 word max_buffer_size
;
2203 /* Reception buffer size (buffer is allocated below) is always as large as the
2204 * maximum transmission buffer size, and could be larger if the transmission
2205 * buffer size is smaller than 8000 bytes.
2207 if (server
->max_recv
<= 0)
2208 server
->max_recv
= given_max_xmit
< 8000 ? 8000 : given_max_xmit
;
2210 if ((result
= smb_connect (server
)) < 0) /* this is really a plain connect() call */
2212 LOG (("smb_proc_reconnect: could not smb_connect\n"));
2216 /* Here we assume that the connection is valid */
2217 server
->state
= CONN_VALID
;
2219 if (server
->packet
!= NULL
)
2220 free (server
->packet
);
2222 server
->packet
= malloc (server
->max_recv
);
2223 if (server
->packet
== NULL
)
2225 LOG (("smb_proc_connect: No memory! Bailing out.\n"));
2230 packet
= server
->packet
;
2232 server
->max_buffer_size
= default_max_buffer_size
;
2234 /* Prepend a NetBIOS header? */
2235 if(!server
->raw_smb
)
2237 /* Start with an RFC1002 session request packet. */
2240 p
= smb_name_mangle (p
, server
->mount_data
.server_name
);
2241 p
= smb_name_mangle (p
, server
->mount_data
.client_name
);
2243 smb_encode_smb_length (packet
, (byte
*) p
- (byte
*) (packet
));
2245 packet
[0] = 0x81; /* SESSION REQUEST */
2247 if ((result
= smb_request (server
)) < 0)
2249 LOG (("smb_proc_connect: Failed to send SESSION REQUEST.\n"));
2253 if (packet
[0] != 0x82)
2255 LOG (("smb_proc_connect: Did not receive positive response (err = %lx)\n",packet
[0]));
2259 smb_dump_packet (packet
);
2267 LOG (("smb_proc_connect: Passed SESSION REQUEST.\n"));
2270 /* Now we are ready to send a SMB Negotiate Protocol packet. */
2272 for (i
= 0; i
< num_prots
; i
++)
2273 plength
+= strlen (prots
[i
].name
) + 2;
2275 smb_setup_header (server
, SMBnegprot
, 0, plength
);
2277 p
= SMB_BUF (packet
);
2279 for (i
= 0; i
< num_prots
; i
++)
2280 p
= smb_encode_dialect (p
, prots
[i
].name
, strlen (prots
[i
].name
));
2282 LOG (("smb_proc_connect: Request SMBnegprot...\n"));
2283 if ((result
= smb_request_ok (server
, SMBnegprot
, 1, -1)) < 0)
2285 LOG (("smb_proc_connect: Failure requesting SMBnegprot\n"));
2289 LOG (("Verified!\n"));
2291 p
= SMB_VWV (packet
);
2293 smb_decode_word (p
, &dialect_index
);
2295 /* If the server does not support any of the listed
2296 * dialects, ist must return a dialect index of 0xFFFF.
2298 if(dialect_index
> num_prots
|| dialect_index
== 0xFFFFU
)
2300 LOG (("smb_proc_connect: Unsupported dialect\n"));
2306 server
->protocol
= prots
[dialect_index
].prot
;
2308 LOG (("smb_proc_connect: Server wants %s protocol.\n",prots
[dialect_index
].name
));
2310 if (server
->protocol
> PROTOCOL_LANMAN1
)
2312 int user_len
= strlen (server
->mount_data
.username
)+1;
2313 dword server_sesskey
;
2315 LOG (("smb_proc_connect: password = %s\n",server
->mount_data
.password
));
2316 LOG (("smb_proc_connect: usernam = %s\n",server
->mount_data
.username
));
2317 LOG (("smb_proc_connect: blkmode = %ld\n",WVAL (packet
, smb_vwv5
)));
2319 /* NT LAN Manager or newer. */
2320 if (server
->protocol
>= PROTOCOL_NT1
)
2322 server
->security_mode
= BVAL(packet
, smb_vwv1
);
2323 max_buffer_size
= DVAL (packet
, smb_vwv3
+ 1);
2324 server
->max_raw_size
= DVAL (packet
, smb_vwv5
+ 1);
2325 server_sesskey
= DVAL (packet
, smb_vwv7
+ 1);
2326 server
->capabilities
= DVAL (packet
, smb_vwv9
+ 1);
2327 server
->crypt_key_length
= BVAL (packet
, smb_vwv16
+ 1);
2329 memcpy(server
->crypt_key
,SMB_BUF(packet
),server
->crypt_key_length
);
2331 /* LAN Manager 2.0 or older */
2336 server
->security_mode
= BVAL(packet
, smb_vwv1
);
2337 max_buffer_size
= WVAL (packet
, smb_vwv2
);
2338 /* Maximum raw read/write size is fixed to 65535 bytes. */
2339 server
->max_raw_size
= 65535;
2340 blkmode
= WVAL (packet
, smb_vwv5
);
2341 server_sesskey
= DVAL (packet
, smb_vwv6
);
2343 /* Crypt key size is fixed to 8 bytes. */
2344 server
->crypt_key_length
= 8;
2346 memcpy(server
->crypt_key
,SMB_BUF(packet
),server
->crypt_key_length
);
2348 /* We translate this into capabilities. According to the
2349 LAN Manager 1.x/2.0 documentation both bits 0+1 being set
2350 means the same thing as CAP_RAW_MODE being set. */
2351 if((blkmode
& 3) == 3)
2352 server
->capabilities
= CAP_RAW_MODE
;
2355 SHOWVALUE(server
->security_mode
);
2357 if(server
->security_mode
& NEGOTIATE_ENCRYPT_PASSWORDS
)
2359 SHOWMSG("encrypted passwords required");
2361 memset(password
,0,sizeof(password
));
2362 strlcpy(password
,server
->mount_data
.password
,sizeof(password
));
2364 smb_encrypt(password
,server
->crypt_key
,password
);
2368 PRINTF(("password: "));
2369 for(i
= 0 ; i
< 24 ; i
++)
2370 PRINTF(("%02lx ",password
[i
]));
2373 memset(nt_password
,0,sizeof(nt_password
));
2374 strlcpy(nt_password
,server
->mount_data
.password
,sizeof(nt_password
));
2376 smb_nt_encrypt(nt_password
,server
->crypt_key
,nt_password
);
2377 nt_password_len
= 24;
2380 PRINTF(("nt_password: "));
2381 for(i
= 0 ; i
< 24 ; i
++)
2382 PRINTF(("%02lx ",nt_password
[i
]));
2386 PRINTF(("crypt_key: "));
2387 for(i
= 0 ; i
< server
->crypt_key_length
; i
++)
2388 PRINTF(("%02lx ",server
->crypt_key
[i
]));
2393 SHOWMSG("plain text passwords sufficient");
2395 password_len
= strlen(server
->mount_data
.password
)+1;
2396 nt_password_len
= 0;
2399 /* If in share level security then don't send a password now */
2400 if((server
->security_mode
& NEGOTIATE_USER_SECURITY
) == 0)
2402 SHOWMSG("share level security; zapping passwords");
2403 strcpy(password
,"");
2406 strcpy(nt_password
,"");
2407 nt_password_len
= 0;
2410 SHOWVALUE(password_len
);
2411 SHOWVALUE(nt_password_len
);
2413 LOG (("smb_proc_connect: workgroup = %s\n", server
->mount_data
.workgroup_name
));
2415 /* NT LAN Manager or newer. */
2416 if (server
->protocol
>= PROTOCOL_NT1
)
2418 #if !defined(__AROS__)
2419 char *OS_id
= "AmigaOS";
2421 char *OS_id
= "AROS";
2423 char *client_id
= "smbfs";
2425 SHOWMSG("server->protocol >= PROTOCOL_NT1");
2427 smb_setup_header (server
, SMBsesssetupX
, 13, user_len
+ password_len
+ nt_password_len
+ strlen (server
->mount_data
.workgroup_name
)+1 + strlen (OS_id
)+1 + strlen (client_id
)+1);
2429 WSET (packet
, smb_vwv0
, 0xff);
2430 WSET (packet
, smb_vwv2
, given_max_xmit
);
2431 WSET (packet
, smb_vwv3
, 2);
2432 WSET (packet
, smb_vwv4
, 0); /* server->pid */
2433 DSET (packet
, smb_vwv5
, server_sesskey
);
2434 WSET (packet
, smb_vwv7
, password_len
);
2435 WSET (packet
, smb_vwv8
, nt_password_len
);
2436 DSET (packet
, smb_vwv9
, 0); /* reserved */
2437 DSET (packet
, smb_vwv11
, server
->capabilities
& 0x00800000); /* capabilities: Unix support. */
2439 p
= SMB_BUF (packet
);
2441 if(nt_password_len
!= 0)
2443 SHOWMSG("adding encrypted passwords");
2445 memcpy (p
, password
, password_len
);
2448 memcpy (p
, nt_password
, nt_password_len
);
2449 p
+= nt_password_len
;
2453 SHOWMSG("adding plain text password");
2455 memcpy (p
, server
->mount_data
.password
, password_len
);
2459 memcpy (p
, server
->mount_data
.username
, user_len
);
2462 strcpy (p
, server
->mount_data
.workgroup_name
);
2463 p
+= strlen (p
) + 1;
2466 p
+= strlen (p
) + 1;
2468 strcpy (p
, client_id
);
2470 /* LAN Manager 2.0 or older */
2473 smb_setup_header (server
, SMBsesssetupX
, 10, user_len
+ password_len
);
2475 WSET (packet
, smb_vwv0
, 0xff); /* No further ANDX command */
2476 WSET (packet
, smb_vwv1
, 0); /* ANDX offset = 0 */
2478 WSET (packet
, smb_vwv2
, given_max_xmit
); /* maximum buffer size */
2479 WSET (packet
, smb_vwv3
, 2); /* maximum mpx count; should be copied from server */
2480 WSET (packet
, smb_vwv4
, 0); /* server->pid */
2481 DSET (packet
, smb_vwv5
, server_sesskey
);
2482 WSET (packet
, smb_vwv7
, password_len
); /* case sensitive password length */
2483 WSET (packet
, smb_vwv8
, 0); /* offset to encrypted password */
2485 p
= SMB_BUF (packet
);
2486 memcpy (p
, server
->mount_data
.password
, password_len
);
2489 memcpy (p
, server
->mount_data
.username
, user_len
);
2492 if ((result
= smb_request_ok (server
, SMBsesssetupX
, 3, 0)) < 0)
2494 LOG (("smb_proc_connect: SMBsessetupX failed\n"));
2498 smb_decode_word (packet
+ 32, &(server
->server_uid
));
2502 max_buffer_size
= 0;
2503 server
->capabilities
= 0;
2505 password_len
= strlen(server
->mount_data
.password
)+1;
2507 nt_password_len
= 0;
2510 if(nt_password_len
> 0)
2512 strlcpy(full_share
,"//",sizeof(full_share
));
2513 strlcat(full_share
,server
->mount_data
.server_name
,sizeof(full_share
));
2514 strlcat(full_share
,"/",sizeof(full_share
));
2515 strlcat(full_share
,server
->mount_data
.service
,sizeof(full_share
));
2517 full_share_len
= strlen(full_share
);
2519 for(i
= 0 ; i
< full_share_len
; i
++)
2521 if(full_share
[i
] == '/')
2522 full_share
[i
] = '\\';
2525 StringToUpper(full_share
);
2527 SHOWSTRING(full_share
);
2529 smb_setup_header (server
, SMBtconX
, 4, password_len
+ full_share_len
+1 + strlen(dev
)+1);
2531 WSET (packet
, smb_vwv0
, 0xFF);
2532 WSET (packet
, smb_vwv3
, password_len
);
2534 p
= SMB_BUF (packet
);
2536 if(nt_password_len
> 0)
2537 memcpy(p
,password
,password_len
);
2539 memcpy (p
, server
->mount_data
.password
, password_len
);
2543 memcpy(p
,full_share
,full_share_len
+1);
2544 p
+= full_share_len
+1;
2548 if ((result
= smb_request_ok (server
, SMBtconX
, 3, 0)) < 0)
2550 SHOWVALUE(SMB_WCT(packet
));
2552 LOG (("smb_proc_connect: SMBtconX not verified.\n"));
2556 SHOWVALUE(SMB_WCT(packet
));
2558 /* Changed, max_buffer_size hasn't been updated if a tconX message was send instead of tcon. */
2559 if (max_buffer_size
!= 0)
2560 server
->max_buffer_size
= max_buffer_size
;
2562 server
->tid
= WVAL(packet
,smb_tid
);
2566 word decoded_max_xmit
;
2568 /* Fine! We have a connection, send a tcon message. */
2569 smb_setup_header (server
, SMBtcon
, 0, 6 + strlen (server
->mount_data
.service
) + strlen (server
->mount_data
.password
) + strlen (dev
));
2571 p
= SMB_BUF (packet
);
2572 p
= smb_encode_ascii (p
, server
->mount_data
.service
, strlen (server
->mount_data
.service
));
2573 p
= smb_encode_ascii (p
, server
->mount_data
.password
, strlen (server
->mount_data
.password
));
2574 (void) smb_encode_ascii (p
, dev
, strlen (dev
));
2576 if ((result
= smb_request_ok (server
, SMBtcon
, 2, 0)) < 0)
2578 LOG (("smb_proc_connect: SMBtcon not verified.\n"));
2582 LOG (("OK! Managed to set up SMBtcon!\n"));
2584 p
= SMB_VWV (packet
);
2585 p
= smb_decode_word (p
, &decoded_max_xmit
);
2587 server
->max_buffer_size
= decoded_max_xmit
;
2589 SHOWVALUE(server
->max_buffer_size
);
2591 /* Added by Brian Willette - We were ignoring the server's initial
2593 if (max_buffer_size
!= 0 && server
->max_buffer_size
> max_buffer_size
)
2594 server
->max_buffer_size
= max_buffer_size
;
2596 (void) smb_decode_word (p
, &server
->tid
);
2599 SHOWVALUE(server
->max_buffer_size
);
2601 /* Ok, everything is fine. max_buffer_size does not include
2602 the SMB session header of 4 bytes. */
2603 if (server
->max_buffer_size
< 65535 - 4)
2604 server
->max_buffer_size
+= 4;
2606 /* Changed, max_buffer_size hasn't been updated if a tconX message was send instead of tcon. */
2607 if (server
->max_buffer_size
> given_max_xmit
)
2608 server
->max_buffer_size
= given_max_xmit
;
2610 LOG (("max_buffer_size = %ld, tid = %ld\n", server
->max_buffer_size
, server
->tid
));
2612 LOG (("smb_proc_connect: Normal exit\n"));
2618 server
->state
= CONN_INVALID
;
2623 /* smb_proc_reconnect: server->packet is allocated with
2624 server->max_buffer_size bytes if and only if we return >= 0 */
2626 smb_proc_connect (struct smb_server
*server
)
2630 result
= smb_proc_reconnect (server
);
2632 if ((result
< 0) && (server
->packet
!= NULL
))
2634 free (server
->packet
);
2635 server
->packet
= NULL
;
2641 /* error code stuff - put together by Merik Karman
2642 merik -at- blackadder -dot- dsh -dot- oz -dot- au */
2650 /* Dos Error Messages */
2651 static const err_code_struct dos_msgs
[] =
2653 {"ERRbadfunc", 1, "Invalid function"},
2654 {"ERRbadfile", 2, "File not found"},
2655 {"ERRbadpath", 3, "Directory invalid"},
2656 {"ERRnofids", 4, "No file descriptors available"},
2657 {"ERRnoaccess", 5, "Access denied"},
2658 {"ERRbadfid", 6, "Invalid file handle"},
2659 {"ERRbadmcb", 7, "Memory control blocks destroyed"},
2660 {"ERRnomem", 8, "Insufficient server memory to perform the requested function"},
2661 {"ERRbadmem", 9, "Invalid memory block address"},
2662 {"ERRbadenv", 10, "Invalid environment"},
2663 {"ERRbadformat", 11, "Invalid format"},
2664 {"ERRbadaccess", 12, "Invalid open mode"},
2665 {"ERRbaddata", 13, "Invalid data"},
2666 {"ERR", 14, "reserved"},
2667 {"ERRbaddrive", 15, "Invalid drive specified"},
2668 {"ERRremcd", 16, "A Delete Directory request attempted to remove the server's current directory"},
2669 {"ERRdiffdevice", 17, "Not same device"},
2670 {"ERRnofiles", 18, "A File Search command can find no more files matching the specified criteria"},
2671 {"ERRbadshare", 32, "The sharing mode specified for an Open conflicts with existing FIDs on the file"},
2672 {"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"},
2673 {"ERRnosuchshare", 67, "Share name not found"},
2674 {"ERRfilexists", 80, "The file named in a Create Directory, Make New File or Link request already exists"},
2675 {"ERRpaused", 81, "The server is temporarily paused"},
2676 {"ERRtimeout", 88, "The requested operation on a named pipe or an I/O device has timed out"},
2677 {"ERRnoresource", 89, "No resources currently available for this SMB request"},
2678 {"ERRtoomanyuids", 90, "Too many UIDs active for this SMB connection"},
2679 {"ERRbaduid", 91, "The UID supplied is not known to the session, or the user identified by the UID does not have sufficient privileges"},
2680 {"ERRbadpipe", 230, "Pipe invalid"},
2681 {"ERRpipebusy", 231, "All instances of the requested pipe are busy"},
2682 {"ERRpipeclosing", 232, "Pipe close in progress"},
2683 {"ERRnotconnected", 233, "No process on other end of pipe"},
2684 {"ERRmoredata", 234, "There is more data to be returned"},
2685 {"ERROR_EAS_DIDNT_FIT", 275, "Either there are no extended attributes, or the available extended attributes did not fit into the response"},
2686 {"ERROR_EAS_NOT_SUPPORTED", 282, "The server file system does not support Extended Attributes"},
2691 /* Server Error Messages */
2692 static const err_code_struct server_msgs
[] =
2694 {"ERRerror", 1, "Non-specific error code"},
2695 {"ERRbadpw", 2, "Bad password - name/password pair in a Tree Connect or Session Setup are invalid"},
2696 {"ERRbadtype", 3, "reserved"},
2697 {"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"},
2698 {"ERRinvnid", 5, "The tree ID (TID) specified in a command was invalid"},
2699 {"ERRinvnetname", 6, "Invalid network name in tree connect"},
2700 {"ERRinvdevice", 7, "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection"},
2701 {"ERRqfull", 49, "Print queue full (files) -- returned by open print file"},
2702 {"ERRqtoobig", 50, "Print queue full -- no space"},
2703 {"ERRqeof", 51, "EOF on print queue dump"},
2704 {"ERRinvpfid", 52, "Invalid print file FID"},
2705 {"ERRsmbcmd", 64, "The server did not recognize the command received"},
2706 {"ERRsrverror", 65, "The server encountered an internal error, e.g., system file unavailable"},
2707 {"ERRfilespecs", 67, "The file handle (FID) and pathname parameters contained an invalid combination of values"},
2708 {"ERRreserved", 68, "reserved"},
2709 {"ERRbadpermits", 69, "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute"},
2710 {"ERRreserved", 70, "reserved"},
2711 {"ERRsetattrmode", 71, "The attribute mode in the Set File Attribute request is invalid"},
2712 {"ERRpaused", 81, "Server is paused"},
2713 {"ERRmsgoff", 82, "Not receiving messages"},
2714 {"ERRnoroom", 83, "No room to buffer message"},
2715 {"ERRrmuns", 87, "Too many remote user names"},
2716 {"ERRtimeout", 88, "Operation timed out"},
2717 {"ERRnoresource", 89, "No resources currently available for request"},
2718 {"ERRtoomanyuids", 90, "Too many UIDs active on this session"},
2719 {"ERRbaduid", 91, "The UID is not known as a valid ID on this session"},
2720 {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode"},
2721 {"ERRusestd", 251, "Temp unable to support Raw, use standard read/write"},
2722 {"ERRcontmpx", 252, "Continue in MPX mode"},
2723 {"ERRreserved", 253, "reserved"},
2724 {"ERRbadPW", 254, "Invalid password"},
2725 {"ERRaccountExpired", 2239, "User account on the target machine is disabled or has expired"},
2726 {"ERRbadClient", 2240, "The client does not have permission to access this server"},
2727 {"ERRbadLogonTime", 2241, "Access to the server is not permitted at this time"},
2728 {"ERRpasswordExpired", 2242, "The user's password has expired"},
2729 {"ERRnosupport", 0xFFFF, "Function not supported"},
2734 /* Hard Error Messages */
2735 static const err_code_struct hard_msgs
[] =
2737 {"ERRnowrite", 19, "Attempt to write on write-protected diskette"},
2738 {"ERRbadunit", 20, "Unknown unit"},
2739 {"ERRnotready", 21, "Drive not ready"},
2740 {"ERRbadcmd", 22, "Unknown command"},
2741 {"ERRdata", 23, "Data error (CRC)"},
2742 {"ERRbadreq", 24, "Bad request structure length"},
2743 {"ERRseek", 25, "Seek error"},
2744 {"ERRbadmedia", 26, "Unknown media type"},
2745 {"ERRbadsector", 27, "Sector not found"},
2746 {"ERRnopaper", 28, "Printer out of paper"},
2747 {"ERRwrite", 29, "Write fault"},
2748 {"ERRread", 30, "Read fault"},
2749 {"ERRgeneral", 31, "General failure"},
2750 {"ERRbadshare", 32, "A open conflicts with an existing open"},
2751 {"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"},
2752 {"ERRwrongdisk", 34, "The wrong disk was found in a drive"},
2753 {"ERRFCBUnavail", 35, "No FCBs are available to process request"},
2754 {"ERRsharebufexc", 36, "A sharing buffer has been exceeded"},
2755 {"ERRdiskfull", 39, "The file system is full"},
2764 const err_code_struct
*err_msgs
;
2767 static const err_class_struct err_classes
[] =
2769 { 0, "SUCCESS", NULL
},
2770 { 0x01, "ERRDOS", dos_msgs
},
2771 { 0x02, "ERRSRV", server_msgs
},
2772 { 0x03, "ERRHRD", hard_msgs
},
2773 { 0x04, "ERRXOS", NULL
},
2774 { 0xE1, "ERRRMX1", NULL
},
2775 { 0xE2, "ERRRMX2", NULL
},
2776 { 0xE3, "ERRRMX3", NULL
},
2777 { 0xFF, "ERRCMD", NULL
},
2783 smb_printerr (int class, int num
)
2786 err_code_struct
*err
;
2788 for (i
= 0; err_classes
[i
].class; i
++)
2790 if (err_classes
[i
].code
!= class)
2793 if (!err_classes
[i
].err_msgs
)
2795 ReportError("%s - %ld.", err_classes
[i
].class, num
);
2797 LOG (("%s - %ld\n", err_classes
[i
].class, num
));
2801 err
= (err_code_struct
*)err_classes
[i
].err_msgs
;
2803 for (j
= 0; err
[j
].name
; j
++)
2805 if (num
!= err
[j
].code
)
2808 ReportError ("%s - %s (%s).", err_classes
[i
].class, err
[j
].name
, err
[j
].message
);
2810 LOG (("%s - %s (%s)\n",err_classes
[i
].class, err
[j
].name
,err
[j
].message
));
2815 ReportError ("Unknown error - (%ld, %ld).", class, num
);
2817 LOG (("Unknown error - (%ld, %ld)\n", class, num
));