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(byte
*packet
);
43 static INLINE
int smb_verify(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(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(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] | p
[1] << 8;
89 smb_encode_smb_length (byte
* p
, dword len
)
92 p
[2] = (len
& 0xFF00) >> 8;
102 smb_encode_dialect (byte
* p
, const byte
* name
, int len
)
111 smb_encode_ascii (byte
* p
, const byte
* name
, int len
)
120 smb_encode_vblock (byte
* p
, const byte
* data
, word len
, int unused_fs
)
123 p
= smb_encode_word (p
, len
);
124 memcpy (p
, data
, len
);
128 smb_decode_data (byte
* p
, byte
* data
, word
* data_len
, int unused_fs
)
132 if (!((*p
) == 1 || (*p
) == 5))
133 LOG (("Warning! Data block not starting with 1 or 5\n"));
138 memcpy (data
, p
, len
);
146 smb_name_mangle (byte
* p
, const byte
* name
)
155 (*p
++) = 2 * (len
+ pad
);
157 while ((*name
) != '\0')
159 (*p
++) = ((*name
) >> 4) + 'A';
160 (*p
++) = ((*name
) & 0x0F) + 'A';
176 /* According to the core protocol documentation times are
177 expressed as seconds past January 1st, 1970, local
180 utc2local (int time_value
)
185 result
= time_value
- GetTimeZoneDelta();
193 local2utc (int time_value
)
198 result
= time_value
+ GetTimeZoneDelta();
205 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since January 1st 1970). */
207 date_dos2unix (unsigned short time_value
, unsigned short date
)
212 memset(&tm
,0,sizeof(tm
));
214 tm
.tm_sec
= 2 * (time_value
& 0x1F);
215 tm
.tm_min
= (time_value
>> 5) & 0x3F;
216 tm
.tm_hour
= (time_value
>> 11) & 0x1F;
217 tm
.tm_mday
= date
& 0x1F;
218 tm
.tm_mon
= ((date
>> 5) & 0xF) - 1;
219 tm
.tm_year
= ((date
>> 9) & 0x7F) + 80;
221 seconds
= MakeTime(&tm
);
226 /* Convert linear UNIX date to a MS-DOS time/date pair. */
228 date_unix2dos (int unix_date
, unsigned short *time_value
, unsigned short *date
)
232 GMTime(unix_date
,&tm
);
234 (*time_value
) = (tm
.tm_hour
<< 11) | (tm
.tm_min
<< 5) | (tm
.tm_sec
/ 2);
235 (*date
) = ((tm
.tm_year
- 80) << 9) | ((tm
.tm_mon
+ 1) << 5) | tm
.tm_mday
;
238 /****************************************************************************
242 ****************************************************************************/
244 smb_len (byte
* packet
)
246 return (dword
)( (((dword
)(packet
[1] & 0x1)) << 16) | (((dword
)packet
[2]) << 8) | (packet
[3]) );
250 smb_bcc (byte
* packet
)
252 int pos
= SMB_HEADER_LEN
+ SMB_WCT (packet
) * sizeof (word
);
254 return (word
)(packet
[pos
] | packet
[pos
+ 1] << 8);
257 /* smb_valid_packet: We check if packet fulfills the basic
258 requirements of a smb packet */
260 smb_valid_packet (byte
* packet
)
264 LOG (("len: %ld, wct: %ld, bcc: %ld -- SMB_HEADER_LEN[%ld] + SMB_WCT (packet) * 2[%ld] + SMB_BCC (packet)[%ld] + 2 = %ld\n",
269 SMB_WCT (packet
) * 2,
271 SMB_HEADER_LEN
+ SMB_WCT (packet
) * 2 + SMB_BCC (packet
) + 2));
273 /* olsen: During protocol negotiation Samba 3.2.5 may return SMB responses which contain
274 more data than is called for. I'm not sure what the right approach to handle
275 this would be. But for now, I've modified this test to check only if there
276 is less data in a response than required. */
277 result
= (packet
[4] == 0xff
281 && (smb_len (packet
) + 4 >= (dword
)
282 (SMB_HEADER_LEN
+ SMB_WCT (packet
) * 2 + SMB_BCC (packet
) + 2))) ? 0 : (-EIO
);
287 /* smb_verify: We check if we got the answer we expected, and if we
288 got enough data. If bcc == -1, we don't care. */
290 smb_verify (byte
* packet
, int command
, int wct
, int bcc
)
292 return (SMB_CMD (packet
) == command
&&
293 SMB_WCT (packet
) >= wct
&&
294 (bcc
== -1 || SMB_BCC (packet
) >= bcc
)) ? 0 : -EIO
;
298 smb_errno (int errcls
, int error
)
303 smb_printerr (errcls
, error
);
305 if (errcls
== ERRDOS
)
307 static const int map
[][2] =
309 { ERRbadfunc
,EINVAL
},
310 { ERRbadfile
,ENOENT
},
311 { ERRbadpath
,ENOENT
},
312 { ERRnofids
,EMFILE
},
313 { ERRnoaccess
,EACCES
},
317 { ERRbadmem
,EFAULT
},
319 { ERRbadformat
,EIO
},
320 { ERRbadaccess
,EACCES
},
321 { ERRbaddata
,E2BIG
},
322 { ERRbaddrive
,ENXIO
},
324 { ERRdiffdevice
,EXDEV
},
326 { ERRbadshare
,ETXTBSY
},
328 { ERRfilexists
,EEXIST
},
329 { 87,0 },/* Unknown error! */
330 { 183,EEXIST
},/* This next error seems to occur on an mv when
331 the destination exists */
337 for(i
= 0 ; map
[i
][0] != -1 ; i
++)
339 if(map
[i
][0] == error
)
346 else if (errcls
== ERRSRV
)
348 static const int map
[][2] =
353 { ERRaccess
,EACCES
},
359 for(i
= 0 ; map
[i
][0] != -1 ; i
++)
361 if(map
[i
][0] == error
)
368 else if (errcls
== ERRHRD
)
370 static const int map
[][2] =
372 { ERRnowrite
,EROFS
},
373 { ERRbadunit
,ENODEV
},
374 { ERRnotready
,EBUSY
},
377 { ERRbadreq
,ERANGE
},
378 { ERRbadshare
,ETXTBSY
},
385 for(i
= 0 ; map
[i
][0] != -1 ; i
++)
387 if(map
[i
][0] == error
)
394 else if (errcls
== ERRCMD
)
411 if ((c
< ' ') || (c
> '~'))
418 smb_dump_packet (byte
* packet
)
423 errcls
= (int) packet
[9];
424 error
= (int) (int) (packet
[11] | packet
[12] << 8);
426 LOG (("smb_len = %ld valid = %ld \n", len
= smb_len (packet
), smb_valid_packet (packet
)));
427 LOG (("smb_cmd = %ld smb_wct = %ld smb_bcc = %ld\n", packet
[8], SMB_WCT (packet
), SMB_BCC (packet
)));
428 LOG (("smb_rcls = %ld smb_err = %ld\n", errcls
, error
));
431 smb_printerr (errcls
, error
);
438 for (i
= 0; i
< len
; i
+= 10)
440 PRINTF (("%03ld:", i
));
442 for (j
= i
; j
< i
+ 10; j
++)
445 PRINTF (("%02lx ", packet
[j
]));
452 for (j
= i
; j
< i
+ 10; j
++)
455 PRINTF (("%lc", print_char (packet
[j
])));
464 /* smb_request_ok: We expect the server to be locked. Then we do the
465 request and check the answer completely. When smb_request_ok
466 returns 0, you can be quite sure that everything went well. When
467 the answer is <=0, the returned number is a valid unix errno. */
469 smb_request_ok (struct smb_server
*s
, int command
, int wct
, int bcc
)
477 result
= smb_request (s
);
480 LOG (("smb_request failed\n"));
482 else if ((error
= smb_valid_packet (s
->packet
)) != 0)
484 LOG (("not a valid packet!\n"));
487 else if (s
->rcls
!= 0)
489 result
= -smb_errno (s
->rcls
, s
->err
);
491 else if ((error
= smb_verify (s
->packet
, command
, wct
, bcc
)) != 0)
493 LOG (("smb_verify failed\n"));
500 /* smb_retry: This function should be called when smb_request_ok has
501 indicated an error. If the error was indicated because the
502 connection was killed, we try to reconnect. If smb_retry returns 0,
503 the error was indicated for another reason, so a retry would not be
506 smb_retry (struct smb_server
*server
)
510 if (server
->state
== CONN_VALID
)
513 if (smb_release (server
) < 0)
515 LOG (("smb_retry: smb_release failed\n"));
516 server
->state
= CONN_RETRIED
;
520 if (smb_proc_reconnect (server
) < 0)
522 LOG (("smb_proc_reconnect failed\n"));
523 server
->state
= CONN_RETRIED
;
527 server
->state
= CONN_VALID
;
536 smb_request_ok_unlock (struct smb_server
*s
, int command
, int wct
, int bcc
)
540 result
= smb_request_ok (s
, command
, wct
, bcc
);
545 /* smb_setup_header: We completely set up the packet. You only have to
546 insert the command-specific fields */
548 smb_setup_header (struct smb_server
*server
, byte command
, word wct
, word bcc
)
550 dword xmit_len
= SMB_HEADER_LEN
+ wct
* sizeof (word
) + bcc
+ 2;
551 byte
*p
= server
->packet
;
552 byte
*buf
= server
->packet
;
554 /* olsen: we subtract four bytes because smb_encode_smb_length() adds
555 four bytes which are not supposed to be included in the total
556 number of bytes to be sent */
557 p
= smb_encode_smb_length (p
, xmit_len
- 4);
558 /* p = smb_encode_smb_length (p, xmit_len); */
564 BSET (p
, 4, command
);
567 memset (p
, '\0', 19);
571 WSET (buf
, smb_tid
, server
->tid
);
572 WSET (buf
, smb_pid
, 0); /* server->pid */
573 WSET (buf
, smb_uid
, server
->server_uid
);
574 WSET (buf
, smb_mid
, 0); /* server->mid */
576 if (server
->protocol
> PROTOCOL_CORE
)
578 BSET (buf
, smb_flg
, 0x8);
579 WSET (buf
, smb_flg2
, 0x3);
582 (*p
++) = wct
; /* wct */
589 /* smb_setup_header_exclusive waits on server->lock and locks the
590 server, when it's free. You have to unlock it manually when you're
591 finished with server->packet! */
593 smb_setup_header_exclusive (struct smb_server
*server
, byte command
, word wct
, word bcc
)
597 result
= smb_setup_header (server
, command
, wct
, bcc
);
602 /*****************************************************************************
604 * File operation section.
606 ****************************************************************************/
609 smb_proc_open (struct smb_server
*server
, const char *pathname
, int len
, struct smb_dirent
*entry
)
613 char *buf
= server
->packet
;
614 const word o_attr
= aSYSTEM
| aHIDDEN
| aDIR
;
616 LOG (("path=%s\n", pathname
));
620 p
= smb_setup_header (server
, SMBopen
, 2, 2 + len
);
621 WSET (buf
, smb_vwv0
, 0x42); /* read/write */
622 WSET (buf
, smb_vwv1
, o_attr
);
623 smb_encode_ascii (p
, pathname
, len
);
625 if ((error
= smb_request_ok (server
, SMBopen
, 7, 0)) < 0)
627 if (smb_retry (server
))
630 if (error
!= -EACCES
)
633 p
= smb_setup_header (server
, SMBopen
, 2, 2 + len
);
634 WSET (buf
, smb_vwv0
, 0x40); /* read only */
635 WSET (buf
, smb_vwv1
, o_attr
);
636 smb_encode_ascii (p
, pathname
, len
);
638 if ((error
= smb_request_ok (server
, SMBopen
, 7, 0)) < 0)
640 if (smb_retry (server
))
647 /* We should now have data in vwv[0..6]. */
648 entry
->fileid
= WVAL (buf
, smb_vwv0
);
649 entry
->attr
= WVAL (buf
, smb_vwv1
);
650 entry
->ctime
= entry
->atime
= entry
->mtime
= entry
->wtime
= local2utc (DVAL (buf
, smb_vwv2
));
651 entry
->size
= DVAL (buf
, smb_vwv4
);
658 GMTime(entry
->ctime
,&tm
);
659 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
));
661 GMTime(entry
->atime
,&tm
);
662 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
));
664 GMTime(entry
->mtime
,&tm
);
665 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
));
667 GMTime(entry
->wtime
,&tm
);
668 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
));
677 /* smb_proc_close: in finfo->mtime we can send a modification time to
680 smb_proc_close (struct smb_server
*server
, word fileid
, dword mtime
)
682 char *buf
= server
->packet
;
686 if(mtime
!= 0 && mtime
!= 0xffffffff)
688 /* 0 and 0xffffffff mean: do not set mtime */
689 local_time
= utc2local (mtime
);
696 smb_setup_header_exclusive (server
, SMBclose
, 3, 0);
697 WSET (buf
, smb_vwv0
, fileid
);
698 DSET (buf
, smb_vwv1
, local_time
);
700 result
= smb_request_ok_unlock (server
, SMBclose
, 0, 0);
705 /* In smb_proc_read and smb_proc_write we do not retry, because the
706 file-id would not be valid after a reconnection. */
708 /* smb_proc_read: fs indicates if it should be copied with
711 smb_proc_read (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, long count
, char *data
, int fs
)
713 word returned_count
, data_len
;
714 char *buf
= server
->packet
;
718 smb_setup_header_exclusive (server
, SMBread
, 5, 0);
720 WSET (buf
, smb_vwv0
, finfo
->fileid
);
721 WSET (buf
, smb_vwv1
, count
);
722 DSET (buf
, smb_vwv2
, offset
);
723 WSET (buf
, smb_vwv4
, 0);
725 if ((error
= smb_request_ok (server
, SMBread
, 5, -1)) < 0)
731 returned_count
= WVAL (buf
, smb_vwv0
);
733 smb_decode_data (SMB_BUF (server
->packet
), data
, &data_len
, fs
);
735 if (returned_count
!= data_len
)
737 LOG (("Warning, returned_count != data_len\n"));
738 LOG (("ret_c=%ld, data_len=%ld\n", returned_count
, data_len
));
742 LOG (("ret_c=%ld, data_len=%ld\n", returned_count
, data_len
));
752 /* count must be <= 65535. No error number is returned. A result of 0
753 indicates an error, which has to be investigated by a normal read
756 smb_proc_read_raw (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, long count
, char *data
)
758 char *buf
= server
->packet
;
761 smb_setup_header_exclusive (server
, SMBreadbraw
, 8, 0);
763 WSET (buf
, smb_vwv0
, finfo
->fileid
);
764 DSET (buf
, smb_vwv1
, offset
);
765 WSET (buf
, smb_vwv3
, count
);
766 WSET (buf
, smb_vwv4
, 0);
767 DSET (buf
, smb_vwv5
, 0);
769 result
= smb_request_read_raw (server
, data
, count
);
775 smb_proc_write (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, long count
, const char *data
)
778 char *buf
= server
->packet
;
781 p
= smb_setup_header_exclusive (server
, SMBwrite
, 5, count
+ 3);
782 WSET (buf
, smb_vwv0
, finfo
->fileid
);
783 WSET (buf
, smb_vwv1
, count
);
784 DSET (buf
, smb_vwv2
, offset
);
785 WSET (buf
, smb_vwv4
, 0);
789 memcpy (p
+ 2, data
, count
);
791 if ((res
= smb_request_ok (server
, SMBwrite
, 1, 0)) >= 0)
792 res
= WVAL (buf
, smb_vwv0
);
797 /* count must be <= 65535 */
799 smb_proc_write_raw (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, long count
, const char *data
)
801 char *buf
= server
->packet
;
803 long len
= server
->max_xmit
- 4;
809 len
= count
- len
; /* transfer the larger part using the second packet */
811 p
= smb_setup_header_exclusive (server
, SMBwritebraw
, server
->protocol
> PROTOCOL_COREPLUS
? 12 : 11, len
);
813 WSET (buf
, smb_vwv0
, finfo
->fileid
);
814 DSET (buf
, smb_vwv1
, count
);
815 DSET (buf
, smb_vwv3
, offset
);
816 DSET (buf
, smb_vwv5
, 0); /* timeout */
817 WSET (buf
, smb_vwv7
, 1); /* send final result response */
818 DSET (buf
, smb_vwv8
, 0); /* reserved */
820 if (server
->protocol
> PROTOCOL_COREPLUS
)
822 WSET (buf
, smb_vwv10
, len
);
823 WSET (buf
, smb_vwv11
, p
- smb_base(buf
));
827 memcpy (p
, data
, len
);
829 result
= smb_request_ok (server
, SMBwritebraw
, 1, 0);
831 LOG (("first request returned %ld\n", result
));
836 result
= smb_request_write_raw (server
, data
+ len
, count
- len
);
838 LOG(("raw request returned %ld\n", result
));
844 /* We have to do the checks of smb_request_ok here as well */
845 if ((error
= smb_valid_packet (server
->packet
)) != 0)
847 LOG (("not a valid packet!\n"));
850 else if (server
->rcls
!= 0)
852 result
= -smb_errno (server
->rcls
, server
->err
);
854 else if ((error
= smb_verify (server
->packet
, SMBwritec
, 1, 0)) != 0)
856 LOG (("smb_verify failed\n"));
860 /* If everything went fine, the whole block has been transfered. */
861 if (result
== (count
- len
))
871 smb_proc_lseek (struct smb_server
*server
, struct smb_dirent
*finfo
, off_t offset
, int mode
, off_t
* new_position_ptr
)
873 char *buf
= server
->packet
;
878 smb_setup_header (server
, SMBlseek
, 4,0);
880 WSET (buf
, smb_vwv0
, finfo
->fileid
);
881 WSET (buf
, smb_vwv1
, mode
);
882 DSET (buf
, smb_vwv2
, offset
);
884 if ((error
= smb_request_ok (server
, SMBlseek
, 1, 0)) < 0)
886 if (smb_retry (server
))
891 (*new_position_ptr
) = DVAL(buf
, smb_vwv0
);
897 /* smb_proc_lockingX: We don't chain any further packets to the initial one */
899 smb_proc_lockingX (struct smb_server
*server
, struct smb_dirent
*finfo
, struct smb_lkrng
*locks
, int num_entries
, int mode
, long timeout
)
902 int num_locks
, num_unlocks
;
903 char *buf
= server
->packet
;
908 num_locks
= num_unlocks
= 0;
911 num_unlocks
= num_entries
;
913 num_locks
= num_entries
;
917 data
= smb_setup_header(server
, SMBlockingX
, 8, num_entries
* 10);
919 BSET (buf
, smb_vwv0
, 0xFF);
920 WSET (buf
, smb_vwv1
, 0);
921 WSET (buf
, smb_vwv2
, finfo
->fileid
);
922 BSET (buf
, smb_vwv3
, mode
& 1);
923 DSET (buf
, smb_vwv4
, timeout
);
924 WSET (buf
, smb_vwv6
, num_unlocks
);
925 WSET (buf
, smb_vwv7
, num_locks
);
927 for (i
= 0, p
= locks
; i
< num_entries
; i
++, p
++)
929 WSET (data
, SMB_LPID_OFFSET(i
), 0); /* server->pid */
930 DSET (data
, SMB_LKOFF_OFFSET(i
), p
->offset
);
931 DSET (data
, SMB_LKLEN_OFFSET(i
), p
->len
);
934 if ((result
= smb_request_ok (server
, SMBlockingX
, 0, 0)) < 0)
936 if (smb_retry (server
))
943 /* smb_proc_do_create: We expect entry->attry & entry->ctime to be set. */
945 smb_proc_do_create (struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*entry
, word command
)
949 char *buf
= server
->packet
;
954 p
= smb_setup_header (server
, command
, 3, len
+ 2);
955 WSET (buf
, smb_vwv0
, entry
->attr
);
956 local_time
= utc2local (entry
->ctime
);
957 DSET (buf
, smb_vwv1
, local_time
);
958 smb_encode_ascii (p
, path
, len
);
960 if ((error
= smb_request_ok (server
, command
, 1, 0)) < 0)
962 if (smb_retry (server
))
969 entry
->fileid
= WVAL (buf
, smb_vwv0
);
971 smb_proc_close (server
, entry
->fileid
, entry
->mtime
);
979 smb_proc_create (struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*entry
)
981 return smb_proc_do_create (server
, path
, len
, entry
, SMBcreate
);
985 smb_proc_mv (struct smb_server
*server
, const char *opath
, const int olen
, const char *npath
, const int nlen
)
988 char *buf
= server
->packet
;
993 p
= smb_setup_header (server
, SMBmv
, 1, olen
+ nlen
+ 4);
995 WSET (buf
, smb_vwv0
, 0);
997 p
= smb_encode_ascii (p
, opath
, olen
);
998 smb_encode_ascii (p
, npath
, olen
);
1000 if ((result
= smb_request_ok (server
, SMBmv
, 0, 0)) < 0)
1002 if (smb_retry (server
))
1010 smb_proc_mkdir (struct smb_server
*server
, const char *path
, const int len
)
1017 p
= smb_setup_header (server
, SMBmkdir
, 0, 2 + len
);
1019 smb_encode_ascii (p
, path
, len
);
1021 if ((result
= smb_request_ok (server
, SMBmkdir
, 0, 0)) < 0)
1023 if (smb_retry (server
))
1031 smb_proc_rmdir (struct smb_server
*server
, const char *path
, const int len
)
1038 p
= smb_setup_header (server
, SMBrmdir
, 0, 2 + len
);
1040 smb_encode_ascii (p
, path
, len
);
1042 if ((result
= smb_request_ok (server
, SMBrmdir
, 0, 0)) < 0)
1044 if (smb_retry (server
))
1052 smb_proc_unlink (struct smb_server
*server
, const char *path
, const int len
)
1055 char *buf
= server
->packet
;
1060 p
= smb_setup_header (server
, SMBunlink
, 1, 2 + len
);
1062 WSET (buf
, smb_vwv0
, 0);
1064 smb_encode_ascii (p
, path
, len
);
1066 if ((result
= smb_request_ok (server
, SMBunlink
, 0, 0)) < 0)
1068 if (smb_retry (server
))
1076 smb_proc_trunc (struct smb_server
*server
, word fid
, dword length
)
1079 char *buf
= server
->packet
;
1082 p
= smb_setup_header (server
, SMBwrite
, 5, 3);
1083 WSET (buf
, smb_vwv0
, fid
);
1084 WSET (buf
, smb_vwv1
, 0);
1085 DSET (buf
, smb_vwv2
, length
);
1086 WSET (buf
, smb_vwv4
, 0);
1087 smb_encode_ascii (p
, "", 0);
1089 result
= smb_request_ok (server
, SMBwrite
, 1, 0);
1091 result
= DVAL(buf
, smb_vwv0
);
1097 smb_decode_dirent (char *p
, struct smb_dirent
*entry
)
1101 p
+= SMB_STATUS_SIZE
; /* reserved (search_status) */
1103 entry
->attr
= BVAL (p
, 0);
1104 entry
->mtime
= entry
->atime
= entry
->ctime
= entry
->wtime
= date_dos2unix (WVAL (p
, 1), WVAL (p
, 3));
1105 entry
->size
= DVAL (p
, 5);
1109 if(name_size
> entry
->complete_path_size
-1)
1110 name_size
= entry
->complete_path_size
-1;
1112 memcpy (entry
->complete_path
, p
+ 9, name_size
);
1114 entry
->complete_path
[name_size
] = '\0';
1116 LOG (("smb_decode_dirent: path = %s\n", entry
->complete_path
));
1122 GMTime(entry
->ctime
,&tm
);
1123 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
));
1125 GMTime(entry
->atime
,&tm
);
1126 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
));
1128 GMTime(entry
->mtime
,&tm
);
1129 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
));
1131 GMTime(entry
->wtime
,&tm
);
1132 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
));
1139 /* This routine is used to read in directory entries from the network.
1140 Note that it is for short directory name seeks, i.e.: protocol < PROTOCOL_LANMAN2 */
1142 smb_proc_readdir_short (struct smb_server
*server
, char *path
, int fpos
, int cache_size
, struct smb_dirent
*entry
)
1149 int first
, total_count
;
1150 struct smb_dirent
*current_entry
;
1153 char status
[SMB_STATUS_SIZE
];
1154 int entries_asked
= (server
->max_xmit
- 100) / SMB_DIRINFO_SIZE
;
1155 int dirlen
= strlen (path
);
1158 mask
= malloc(dirlen
+ 4 + 1);
1165 strcpy (mask
, path
);
1166 strcat (mask
, "\\*.*");
1168 LOG (("SMB call readdir %ld @ %ld\n", cache_size
, fpos
));
1169 LOG ((" mask = %s\n", mask
));
1171 buf
= server
->packet
;
1177 current_entry
= entry
;
1183 p
= smb_setup_header (server
, SMBsearch
, 2, 5 + strlen (mask
));
1184 WSET (buf
, smb_vwv0
, entries_asked
);
1185 WSET (buf
, smb_vwv1
, aDIR
);
1186 p
= smb_encode_ascii (p
, mask
, strlen (mask
));
1188 (void) smb_encode_word (p
, 0);
1192 p
= smb_setup_header (server
, SMBsearch
, 2, 5 + SMB_STATUS_SIZE
);
1193 WSET (buf
, smb_vwv0
, entries_asked
);
1194 WSET (buf
, smb_vwv1
, aDIR
);
1195 p
= smb_encode_ascii (p
, "", 0);
1196 (void) smb_encode_vblock (p
, status
, SMB_STATUS_SIZE
, 0);
1199 if ((error
= smb_request_ok (server
, SMBsearch
, 1, -1)) < 0)
1201 if ((server
->rcls
== ERRDOS
) && (server
->err
== ERRnofiles
))
1203 result
= total_count
- fpos
;
1208 if (smb_retry (server
))
1217 p
= SMB_VWV (server
->packet
);
1218 p
= smb_decode_word (p
, &count
); /* vwv[0] = count-returned */
1219 p
= smb_decode_word (p
, &bcc
);
1225 result
= total_count
- fpos
;
1230 if (bcc
!= count
* SMB_DIRINFO_SIZE
+ 3)
1237 p
+= 3; /* Skipping VBLOCK header (5, length lo, length hi). */
1239 /* Read the last entry into the status field. */
1240 memcpy (status
, SMB_BUF (server
->packet
) + 3 + (count
- 1) * SMB_DIRINFO_SIZE
, SMB_STATUS_SIZE
);
1242 /* Now we are ready to parse smb directory entries. */
1244 for (i
= 0; i
< count
; i
++)
1246 if (total_count
< fpos
)
1248 p
+= SMB_DIRINFO_SIZE
;
1250 LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n", total_count
, i
, fpos
));
1252 else if (total_count
>= fpos
+ cache_size
)
1254 result
= total_count
- fpos
;
1260 p
= smb_decode_dirent (p
, current_entry
);
1279 /*****************************************************************************/
1281 #if !defined(__AROS__)
1282 /* Interpret an 8 byte "filetime" structure to a 'time_t'.
1283 * It's originally in "100ns units since jan 1st 1601".
1285 * Unlike the Samba implementation of that date conversion
1286 * algorithm this one tries to perform the entire
1287 * calculation using integer operations only.
1290 interpret_long_date(char * p
)
1297 /* Extract the 64 bit time value. */
1298 long_date
.Low
= DVAL(p
,0);
1299 long_date
.High
= DVAL(p
,4);
1301 /* Divide by 10,000,000 to convert the time from 100ns
1302 units into seconds. */
1303 divide_64_by_32(&long_date
,10000000,&long_date
);
1305 /* Adjust by 369 years (11,644,473,600 seconds) to convert
1306 from the epoch beginning on January 1st 1601 to the one
1307 beginning on January 1st 1970 (the Unix epoch). */
1308 adjust
.Low
= 0xb6109100;
1309 adjust
.High
= 0x00000002;
1311 underflow
= subtract_64_from_64_to_64(&long_date
,&adjust
,&long_date
);
1313 /* If the result did not produce an underflow or overflow,
1314 return the number of seconds encoded in the least
1315 significant word of the result. */
1316 if(underflow
== 0 && long_date
.High
== 0)
1317 result
= long_date
.Low
;
1325 interpret_long_date(char * p
)
1330 long_date
= *(UQUAD
*)p
- (0x2B6109100ULL
* 10000000);
1331 sectime
= long_date
/ 10000000;
1333 return((time_t)sectime
);
1337 /*****************************************************************************/
1340 smb_get_dirent_name(char *p
,int level
,char ** name_ptr
,int * len_ptr
)
1344 case 1: /* OS/2 understands this */
1345 (*name_ptr
) = p
+ 27;
1346 (*len_ptr
) = strlen(p
+ 27);
1349 case 2: /* this is what OS/2 uses */
1350 (*name_ptr
) = p
+ 31;
1351 (*len_ptr
) = strlen(p
+ 31);
1354 case 3: /* untested */
1355 (*name_ptr
) = p
+ 33;
1356 (*len_ptr
) = strlen(p
+ 33);
1359 case 4: /* untested */
1360 (*name_ptr
) = p
+ 37;
1361 (*len_ptr
) = strlen(p
+ 37);
1364 case 260: /* NT uses this, but also accepts 2 */
1365 (*name_ptr
) = p
+ 94;
1366 (*len_ptr
) = min (DVAL (p
+60, 0), SMB_MAXNAMELEN
);
1376 /* interpret a long filename structure - this is mostly guesses at the
1377 moment. The length of the structure is returned. The structure of
1378 a long filename depends on the info level. 260 is used by NT and 2
1381 smb_decode_long_dirent (char *p
, struct smb_dirent
*finfo
, int level
)
1387 case 1: /* OS/2 understands this */
1393 memcpy(buffer
,p
+ 27,sizeof(buffer
)-1);
1394 buffer
[sizeof(buffer
)-1] = '\0';
1396 LOG(("type=%ld, name='%s'\n",level
,buffer
));
1402 strlcpy (finfo
->complete_path
, p
+ 27, finfo
->complete_path_size
);
1403 finfo
->len
= strlen (finfo
->complete_path
);
1404 finfo
->size
= DVAL (p
, 16);
1405 finfo
->attr
= BVAL (p
, 24);
1406 finfo
->ctime
= date_dos2unix (WVAL (p
, 6), WVAL (p
, 4));
1407 finfo
->atime
= date_dos2unix (WVAL (p
, 10), WVAL (p
, 8));
1408 finfo
->mtime
= date_dos2unix (WVAL (p
, 14), WVAL (p
, 12));
1409 finfo
->wtime
= finfo
->mtime
;
1415 GMTime(finfo
->ctime
,&tm
);
1416 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
));
1418 GMTime(finfo
->atime
,&tm
);
1419 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
));
1421 GMTime(finfo
->mtime
,&tm
);
1422 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
));
1424 GMTime(finfo
->wtime
,&tm
);
1425 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
));
1430 result
= p
+ 28 + BVAL (p
, 26);
1434 case 2: /* this is what OS/2 uses */
1440 memcpy(buffer
,p
+ 31,sizeof(buffer
)-1);
1441 buffer
[sizeof(buffer
)-1] = '\0';
1443 LOG(("type=%ld, name='%s'\n",level
,buffer
));
1449 strlcpy (finfo
->complete_path
, p
+ 31, finfo
->complete_path_size
);
1450 finfo
->len
= strlen (finfo
->complete_path
);
1451 finfo
->size
= DVAL (p
, 16);
1452 finfo
->attr
= BVAL (p
, 24);
1453 finfo
->ctime
= date_dos2unix (WVAL (p
, 6), WVAL (p
, 4));
1454 finfo
->atime
= date_dos2unix (WVAL (p
, 10), WVAL (p
, 8));
1455 finfo
->mtime
= date_dos2unix (WVAL (p
, 14), WVAL (p
, 12));
1456 finfo
->wtime
= finfo
->mtime
;
1462 GMTime(finfo
->ctime
,&tm
);
1463 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
));
1465 GMTime(finfo
->atime
,&tm
);
1466 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
));
1468 GMTime(finfo
->mtime
,&tm
);
1469 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
));
1471 GMTime(finfo
->wtime
,&tm
);
1472 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
));
1477 result
= p
+ 32 + BVAL (p
, 30);
1481 case 260: /* NT uses this, but also accepts 2 */
1488 len
= min (DVAL (p
+60, 0), sizeof(buffer
)-1);
1490 memcpy(buffer
,p
+94,len
);
1493 LOG(("type=%ld, name='%s'\n",level
,buffer
));
1497 result
= p
+ WVAL (p
, 0);
1504 p
+= 4; /* next entry offset */
1505 p
+= 4; /* fileindex */
1506 finfo
->ctime
= interpret_long_date(p
);
1508 finfo
->atime
= interpret_long_date(p
);
1510 finfo
->wtime
= interpret_long_date(p
);
1512 finfo
->mtime
= interpret_long_date(p
);
1514 finfo
->size
= DVAL (p
, 0);
1516 p
+= 8; /* alloc size */
1517 finfo
->attr
= BVAL (p
, 0);
1519 namelen
= min (DVAL (p
, 0), SMB_MAXNAMELEN
);
1521 p
+= 4; /* EA size */
1522 p
+= 2; /* short name len? */
1523 p
+= 24; /* short name? */
1525 if(namelen
> (int)finfo
->complete_path_size
-1)
1526 namelen
= finfo
->complete_path_size
-1;
1528 /* If the modification time is not set, try to
1529 substitute the write time for it. */
1530 if(finfo
->mtime
== 0)
1531 finfo
->mtime
= finfo
->wtime
;
1533 /* Swap last modification time and last write time. */
1534 swap
= finfo
->mtime
;
1535 finfo
->mtime
= finfo
->wtime
;
1536 finfo
->wtime
= swap
;
1538 memcpy (finfo
->complete_path
, p
, namelen
);
1539 finfo
->complete_path
[namelen
] = '\0';
1540 finfo
->len
= namelen
;
1546 GMTime(finfo
->ctime
,&tm
);
1547 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
));
1549 GMTime(finfo
->atime
,&tm
);
1550 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
));
1552 GMTime(finfo
->wtime
,&tm
);
1553 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
));
1555 GMTime(finfo
->mtime
,&tm
);
1556 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
));
1567 /* I have to set times to 0 here, because I do not
1568 have specs about this for all info levels. */
1569 finfo
->ctime
= finfo
->mtime
= finfo
->wtime
= finfo
->atime
= 0;
1572 LOG (("Unknown long filename format %ld\n", level
));
1574 result
= p
+ WVAL (p
, 0);
1583 smb_proc_readdir_long (struct smb_server
*server
, char *path
, int fpos
, int cache_size
, struct smb_dirent
*entry
)
1585 int max_matches
= 512; /* this should actually be based on the max_xmit value */
1587 /* NT uses 260, OS/2 uses 2. Both accept 1. */
1588 int info_level
= server
->protocol
< PROTOCOL_NT1
? 1 : 260;
1593 int total_count
= 0;
1594 struct smb_dirent
*current_entry
;
1598 int resp_data_len
= 0;
1599 int resp_param_len
= 0;
1601 int attribute
= aSYSTEM
| aHIDDEN
| aDIR
;
1607 int ff_dir_handle
= 0;
1608 int ff_resume_key
= 0;
1611 unsigned char *outbuf
= server
->packet
;
1613 int dirlen
= strlen (path
) + 2 + 1;
1619 /* ZZZ experimental 'max_matches' adjustment */
1621 if(info_level == 260)
1622 max_matches = server->max_xmit / 360;
1624 max_matches = server->max_xmit / 40;
1627 SHOWVALUE(server
->max_xmit
);
1628 SHOWVALUE(max_matches
);
1630 mask
= malloc (dirlen
);
1633 LOG (("Memory allocation failed\n"));
1639 strcpy (mask
, path
);
1640 strcat (mask
, "\\*");
1641 masklen
= strlen (mask
);
1643 LOG (("SMB call lreaddir %ld @ %ld\n", cache_size
, fpos
));
1644 LOG ((" mask = %s\n", mask
));
1653 current_entry
= entry
;
1658 if (loop_count
> 200)
1660 LOG (("smb_proc_readdir_long: Looping in FIND_NEXT???\n"));
1666 memset (outbuf
, 0, 39);
1668 smb_setup_header (server
, SMBtrans2
, 15, 5 + 12 + masklen
+ 1);
1670 WSET (outbuf
, smb_tpscnt
, 12 + masklen
+ 1);
1671 WSET (outbuf
, smb_tdscnt
, 0);
1672 WSET (outbuf
, smb_mprcnt
, 10);
1673 WSET (outbuf
, smb_mdrcnt
, server
->max_xmit
);
1674 WSET (outbuf
, smb_msrcnt
, 0);
1675 WSET (outbuf
, smb_flags
, 0);
1676 DSET (outbuf
, smb_timeout
, 0);
1677 WSET (outbuf
, smb_pscnt
, WVAL (outbuf
, smb_tpscnt
));
1678 WSET (outbuf
, smb_psoff
, ((SMB_BUF (outbuf
) + 3) - outbuf
) - 4);
1679 WSET (outbuf
, smb_dscnt
, 0);
1680 WSET (outbuf
, smb_dsoff
, 0);
1681 WSET (outbuf
, smb_suwcnt
, 1);
1682 WSET (outbuf
, smb_setup0
, first
== 1 ? TRANSACT2_FINDFIRST
: TRANSACT2_FINDNEXT
);
1684 p
= SMB_BUF (outbuf
);
1685 (*p
++) = 0; /* put in a null smb_name */
1687 (*p
++) = ' '; /* this was added because OS/2 does it */
1691 LOG (("first match\n"));
1692 WSET (p
, 0, attribute
); /* attribute */
1693 WSET (p
, 2, max_matches
); /* max count */
1694 WSET (p
, 4, 8 + 4 + 2); /* resume required + close on end + continue */
1695 WSET (p
, 6, info_level
);
1700 LOG (("next match; ff_dir_handle=0x%lx ff_resume_key=%ld mask='%s'\n", ff_dir_handle
, ff_resume_key
, mask
));
1701 WSET (p
, 0, ff_dir_handle
);
1702 WSET (p
, 2, max_matches
); /* max count */
1703 WSET (p
, 4, info_level
);
1704 DSET (p
, 6, ff_resume_key
);
1705 WSET (p
, 10, 8 + 4 + 2); /* resume required + close on end + continue */
1711 memcpy (p
, mask
, masklen
);
1717 result
= smb_trans2_request (server
, &resp_data_len
, &resp_param_len
, &resp_data
, &resp_param
);
1719 LOG (("smb_proc_readdir_long: smb_trans2_request returns %ld\n", result
));
1723 if (smb_retry (server
))
1726 LOG (("smb_proc_readdir_long: got error from trans2_request\n"));
1732 /* Apparently, there is a bug in Windows 95 and friends which
1733 causes the directory read attempt to fail if you're asking
1734 for too much data too fast... */
1735 if(server
->rcls
== ERRSRV
&& server
->err
== ERRerror
)
1737 SHOWMSG("ouch; delaying and retrying");
1739 Delay(TICKS_PER_SECOND
/ 5);
1744 if (server
->rcls
!= 0)
1746 LOG (("server->rcls = %ld err = %ld\n",server
->rcls
, server
->err
));
1747 error
= smb_errno (server
->rcls
, server
->err
);
1752 /* ZZZ bail out if this is empty. */
1753 if (resp_param
== NULL
)
1756 /* parse out some important return info */
1760 ff_dir_handle
= WVAL (p
, 0);
1761 ff_searchcount
= WVAL (p
, 2);
1762 ff_eos
= WVAL (p
, 4);
1766 ff_searchcount
= WVAL (p
, 0);
1767 ff_eos
= WVAL (p
, 2);
1770 LOG (("received %ld entries (eos=%ld)\n",ff_searchcount
, ff_eos
));
1771 if (ff_searchcount
== 0)
1774 /* ZZZ bail out if this is empty. */
1775 if (resp_data
== NULL
)
1778 /* point to the data bytes */
1781 /* Now we are ready to parse smb directory entries. */
1782 for (i
= 0; i
< ff_searchcount
; i
++)
1784 if(i
== ff_searchcount
- 1)
1789 ff_resume_key
= DVAL(p
, 0);
1791 smb_get_dirent_name(p
,info_level
,&last_name
,&len
);
1796 char buffer
[SMB_MAXNAMELEN
+1];
1798 memcpy(buffer
,last_name
,len
);
1801 LOG(("last name = '%s'\n",buffer
));
1805 if(len
+ 1 > dirlen
)
1807 D(("increasing mask; old value = %ld new value = %ld",dirlen
,len
+1));
1815 mask
= malloc (dirlen
);
1818 LOG (("smb_proc_readdir_long: Memory allocation failed\n"));
1828 memcpy (mask
, last_name
, len
);
1838 if (total_count
< fpos
)
1840 p
= smb_decode_long_dirent (p
, NULL
, info_level
);
1842 LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n",total_count
, i
, fpos
));
1844 else if (total_count
>= fpos
+ cache_size
)
1846 p
= smb_decode_long_dirent (p
, NULL
, info_level
);
1848 LOG (("smb_proc_readdir: skipped entry; total_count = %ld, i = %ld, fpos = %ld\n",total_count
, i
, fpos
));
1854 p
= smb_decode_long_dirent (p
, current_entry
, info_level
);
1862 SHOWVALUE(ff_resume_key
);
1864 if (resp_data
!= NULL
)
1870 if (resp_param
!= NULL
)
1878 if (ff_searchcount
> 0)
1884 /* finished: not needed any more */
1888 if (resp_data
!= NULL
)
1891 if (resp_param
!= NULL
)
1903 RETURN (total_count
- fpos
);
1904 return (total_count
- fpos
);
1909 smb_proc_readdir (struct smb_server
*server
, char *path
, int fpos
, int cache_size
, struct smb_dirent
*entry
)
1913 if (server
->protocol
>= PROTOCOL_LANMAN2
)
1914 result
= smb_proc_readdir_long (server
, path
, fpos
, cache_size
, entry
);
1916 result
= smb_proc_readdir_short (server
, path
, fpos
, cache_size
, entry
);
1922 smb_proc_getattr_core (struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*entry
)
1926 char *buf
= server
->packet
;
1928 LOG (("smb_proc_getattr: %s\n", path
));
1932 p
= smb_setup_header (server
, SMBgetatr
, 0, 2 + len
);
1933 smb_encode_ascii (p
, path
, len
);
1935 if ((result
= smb_request_ok (server
, SMBgetatr
, 10, 0)) < 0)
1937 if (smb_retry (server
))
1943 entry
->attr
= WVAL (buf
, smb_vwv0
);
1945 /* The server only tells us 1 time */
1946 entry
->ctime
= entry
->atime
= entry
->mtime
= entry
->wtime
= local2utc (DVAL (buf
, smb_vwv1
));
1948 entry
->size
= DVAL (buf
, smb_vwv3
);
1954 GMTime(entry
->ctime
,&tm
);
1955 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
));
1957 GMTime(entry
->atime
,&tm
);
1958 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
));
1960 GMTime(entry
->mtime
,&tm
);
1961 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
));
1963 GMTime(entry
->wtime
,&tm
);
1964 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
));
1973 /* smb_proc_getattrE: entry->fid must be valid */
1975 smb_proc_getattrE (struct smb_server
*server
, struct smb_dirent
*entry
)
1977 char *buf
= server
->packet
;
1980 smb_setup_header_exclusive (server
, SMBgetattrE
, 1, 0);
1981 WSET (buf
, smb_vwv0
, entry
->fileid
);
1983 if ((result
= smb_request_ok (server
, SMBgetattrE
, 11, 0)) < 0)
1986 entry
->ctime
= date_dos2unix (WVAL (buf
, smb_vwv1
), WVAL (buf
, smb_vwv0
));
1987 entry
->atime
= date_dos2unix (WVAL (buf
, smb_vwv3
), WVAL (buf
, smb_vwv2
));
1988 entry
->mtime
= date_dos2unix (WVAL (buf
, smb_vwv5
), WVAL (buf
, smb_vwv4
));
1989 entry
->wtime
= entry
->mtime
;
1990 entry
->size
= DVAL (buf
, smb_vwv6
);
1991 entry
->attr
= WVAL (buf
, smb_vwv10
);
1997 GMTime(entry
->ctime
,&tm
);
1998 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
));
2000 GMTime(entry
->atime
,&tm
);
2001 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
));
2003 GMTime(entry
->mtime
,&tm
);
2004 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
));
2006 GMTime(entry
->wtime
,&tm
);
2007 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
));
2016 /* In core protocol, there is only 1 time to be set, we use
2017 entry->mtime, to make touch work. */
2019 smb_proc_setattr_core (struct smb_server
*server
, const char *path
, int len
, struct smb_dirent
*new_finfo
)
2022 char *buf
= server
->packet
;
2028 LOG (("smb_proc_setattr_core\n"));
2030 p
= smb_setup_header (server
, SMBsetatr
, 8, 4 + len
);
2031 WSET (buf
, smb_vwv0
, new_finfo
->attr
);
2032 local_time
= utc2local (new_finfo
->mtime
);
2033 DSET (buf
, smb_vwv1
, local_time
);
2034 p
= smb_encode_ascii (p
, path
, len
);
2035 (void) smb_encode_ascii (p
, "", 0);
2037 if ((result
= smb_request_ok (server
, SMBsetatr
, 0, 0)) < 0)
2039 if (smb_retry (server
))
2046 /* smb_proc_setattrE: we do not retry here, because we rely on fid,
2047 which would not be valid after a retry. */
2049 smb_proc_setattrE (struct smb_server
*server
, word fid
, struct smb_dirent
*new_entry
)
2051 char *buf
= server
->packet
;
2052 word date
, time_value
;
2055 LOG (("smb_proc_setattrE\n"));
2057 smb_setup_header_exclusive (server
, SMBsetattrE
, 7, 0);
2059 WSET (buf
, smb_vwv0
, fid
);
2061 date_unix2dos (new_entry
->ctime
, &time_value
, &date
);
2062 WSET (buf
, smb_vwv1
, date
);
2063 WSET (buf
, smb_vwv2
, time_value
);
2065 date_unix2dos (new_entry
->atime
, &time_value
, &date
);
2066 WSET (buf
, smb_vwv3
, date
);
2067 WSET (buf
, smb_vwv4
, time_value
);
2069 date_unix2dos (new_entry
->mtime
, &time_value
, &date
);
2070 WSET (buf
, smb_vwv5
, date
);
2071 WSET (buf
, smb_vwv6
, time_value
);
2073 result
= smb_request_ok_unlock (server
, SMBsetattrE
, 0, 0);
2079 smb_proc_dskattr (struct smb_server
*server
, struct smb_dskattr
*attr
)
2086 smb_setup_header (server
, SMBdskattr
, 0, 0);
2088 if ((error
= smb_request_ok (server
, SMBdskattr
, 5, 0)) < 0)
2090 if (smb_retry (server
))
2096 p
= SMB_VWV (server
->packet
);
2097 p
= smb_decode_word (p
, &attr
->total
);
2098 p
= smb_decode_word (p
, &attr
->allocblocks
);
2099 p
= smb_decode_word (p
, &attr
->blocksize
);
2100 (void) smb_decode_word (p
, &attr
->free
);
2107 /*****************************************************************************
2109 * Mount/umount operations.
2111 ****************************************************************************/
2114 enum smb_protocol prot
;
2118 /* smb_proc_reconnect: We expect the server to be locked, so that you
2119 can call the routine from within smb_retry. The socket must be
2120 created, like after a user-level socket()-call. It may not be
2123 smb_proc_reconnect (struct smb_server
*server
)
2125 static const struct smb_prots prots
[] =
2127 {PROTOCOL_CORE
, "PC NETWORK PROGRAM 1.0"},
2128 {PROTOCOL_COREPLUS
, "MICROSOFT NETWORKS 1.03"},
2129 {PROTOCOL_LANMAN1
, "MICROSOFT NETWORKS 3.0"},
2130 {PROTOCOL_LANMAN1
, "LANMAN1.0"},
2131 {PROTOCOL_LANMAN2
, "LM1.2X002"},
2132 {PROTOCOL_NT1
, "NT LM 0.12"},
2133 {PROTOCOL_NT1
, "NT LANMAN 1.0"},
2140 int max_xmit
= 1024; /* Space needed for first request. */
2141 int given_max_xmit
= server
->mount_data
.max_xmit
;
2145 unsigned char password
[24];
2147 unsigned char nt_password
[24];
2148 int nt_password_len
;
2149 unsigned char full_share
[SMB_MAXNAMELEN
+1];
2153 if (server
->max_recv
<= 0)
2154 server
->max_recv
= given_max_xmit
> 8000 ? given_max_xmit
: 8000;
2156 if ((result
= smb_connect (server
)) < 0)
2158 LOG (("smb_proc_reconnect: could not smb_connect\n"));
2162 /* Here we assume that the connection is valid */
2163 server
->state
= CONN_VALID
;
2165 if (server
->packet
!= NULL
)
2166 free (server
->packet
);
2168 server
->packet
= malloc (server
->max_recv
);
2170 if (server
->packet
== NULL
)
2172 LOG (("smb_proc_connect: No memory! Bailing out.\n"));
2177 packet
= server
->packet
;
2179 server
->max_xmit
= max_xmit
;
2181 /* Start with an RFC1002 session request packet. */
2184 p
= smb_name_mangle (p
, server
->mount_data
.server_name
);
2185 p
= smb_name_mangle (p
, server
->mount_data
.client_name
);
2187 smb_encode_smb_length (packet
, (byte
*) p
- (byte
*) (packet
));
2189 packet
[0] = 0x81; /* SESSION REQUEST */
2191 if ((result
= smb_request (server
)) < 0)
2193 LOG (("smb_proc_connect: Failed to send SESSION REQUEST.\n"));
2197 if (packet
[0] != 0x82)
2199 LOG (("smb_proc_connect: Did not receive positive response (err = %lx)\n",packet
[0]));
2203 smb_dump_packet (packet
);
2211 LOG (("smb_proc_connect: Passed SESSION REQUEST.\n"));
2213 /* Now we are ready to send a SMB Negotiate Protocol packet. */
2214 memset (packet
, 0, SMB_HEADER_LEN
);
2217 for (i
= 0; prots
[i
].name
!= NULL
; i
++)
2218 plength
+= strlen (prots
[i
].name
) + 2;
2220 smb_setup_header (server
, SMBnegprot
, 0, plength
);
2222 p
= SMB_BUF (packet
);
2224 for (i
= 0; prots
[i
].name
!= NULL
; i
++)
2225 p
= smb_encode_dialect (p
, prots
[i
].name
, strlen (prots
[i
].name
));
2227 LOG (("smb_proc_connect: Request SMBnegprot...\n"));
2228 if ((result
= smb_request_ok (server
, SMBnegprot
, 1, -1)) < 0)
2230 LOG (("smb_proc_connect: Failure requesting SMBnegprot\n"));
2234 LOG (("Verified!\n"));
2236 p
= SMB_VWV (packet
);
2237 p
= smb_decode_word (p
, &any_word
);
2240 server
->protocol
= prots
[i
].prot
;
2242 LOG (("smb_proc_connect: Server wants %s protocol.\n",prots
[i
].name
));
2244 if (server
->protocol
> PROTOCOL_LANMAN1
)
2246 int user_len
= strlen (server
->mount_data
.username
)+1;
2248 LOG (("smb_proc_connect: password = %s\n",server
->mount_data
.password
));
2249 LOG (("smb_proc_connect: usernam = %s\n",server
->mount_data
.username
));
2250 LOG (("smb_proc_connect: blkmode = %ld\n",WVAL (packet
, smb_vwv5
)));
2252 if (server
->protocol
>= PROTOCOL_NT1
)
2254 server
->maxxmt
= DVAL (packet
, smb_vwv3
+ 1);
2255 server
->blkmode
= DVAL (packet
, smb_vwv9
+ 1);
2256 server
->sesskey
= DVAL (packet
, smb_vwv7
+ 1);
2258 server
->security_mode
= BVAL(packet
, smb_vwv1
);
2260 memcpy(server
->crypt_key
,SMB_BUF(packet
),8);
2264 server
->maxxmt
= WVAL (packet
, smb_vwv2
);
2265 server
->blkmode
= WVAL (packet
, smb_vwv5
);
2266 server
->sesskey
= DVAL (packet
, smb_vwv6
);
2268 server
->security_mode
= BVAL(packet
, smb_vwv1
);
2270 memcpy(server
->crypt_key
,SMB_BUF(packet
),8);
2273 SHOWVALUE(server
->security_mode
);
2275 if(server
->security_mode
& 2)
2277 SHOWMSG("encrypted passwords required");
2279 memset(password
,0,sizeof(password
));
2280 strlcpy(password
,server
->mount_data
.password
,sizeof(password
));
2282 smb_encrypt(password
,server
->crypt_key
,password
);
2286 PRINTF(("password: "));
2287 for(i
= 0 ; i
< 24 ; i
++)
2288 PRINTF(("%02lx ",password
[i
]));
2291 memset(nt_password
,0,sizeof(nt_password
));
2292 strlcpy(nt_password
,server
->mount_data
.password
,sizeof(nt_password
));
2294 smb_nt_encrypt(nt_password
,server
->crypt_key
,nt_password
);
2295 nt_password_len
= 24;
2298 PRINTF(("nt_password: "));
2299 for(i
= 0 ; i
< 24 ; i
++)
2300 PRINTF(("%02lx ",nt_password
[i
]));
2304 PRINTF(("crypt_key: "));
2305 for(i
= 0 ; i
< 8 ; i
++)
2306 PRINTF(("%02lx ",server
->crypt_key
[i
]));
2311 SHOWMSG("plain text passwords sufficient");
2313 password_len
= strlen(server
->mount_data
.password
)+1;
2314 nt_password_len
= 0;
2317 /* If in share level security then don't send a password now */
2318 if((server
->security_mode
& 1) == 0)
2320 SHOWMSG("share level security; zapping passwords");
2321 strcpy(password
,"");
2324 strcpy(nt_password
,"");
2325 nt_password_len
= 0;
2328 SHOWVALUE(password_len
);
2329 SHOWVALUE(nt_password_len
);
2331 LOG (("smb_proc_connect: workgroup = %s\n", server
->mount_data
.workgroup_name
));
2332 if (server
->protocol
>= PROTOCOL_NT1
)
2334 #if !defined(__AROS__)
2335 char *OS_id
= "AmigaOS";
2337 char *OS_id
= "AROS";
2339 char *client_id
= "smbfs";
2341 SHOWMSG("server->protocol >= PROTOCOL_NT1");
2343 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);
2345 WSET (packet
, smb_vwv0
, 0xff);
2346 WSET (packet
, smb_vwv2
, given_max_xmit
);
2347 WSET (packet
, smb_vwv3
, 2);
2348 WSET (packet
, smb_vwv4
, 0); /* server->pid */
2349 DSET (packet
, smb_vwv5
, server
->sesskey
);
2350 WSET (packet
, smb_vwv7
, password_len
);
2351 WSET (packet
, smb_vwv8
, nt_password_len
);
2353 p
= SMB_BUF (packet
);
2355 if(nt_password_len
!= 0)
2357 SHOWMSG("adding encrypted passwords");
2359 memcpy (p
, password
, password_len
);
2362 memcpy (p
, nt_password
, nt_password_len
);
2363 p
+= nt_password_len
;
2367 SHOWMSG("adding plain text password");
2369 memcpy (p
, server
->mount_data
.password
, password_len
);
2373 memcpy (p
, server
->mount_data
.username
, user_len
);
2376 strcpy (p
, server
->mount_data
.workgroup_name
);
2377 p
+= strlen (p
) + 1;
2380 p
+= strlen (p
) + 1;
2382 strcpy (p
, client_id
);
2386 smb_setup_header (server
, SMBsesssetupX
, 10, user_len
+ password_len
);
2388 WSET (packet
, smb_vwv0
, 0xff);
2389 WSET (packet
, smb_vwv1
, 0);
2390 WSET (packet
, smb_vwv2
, given_max_xmit
);
2391 WSET (packet
, smb_vwv3
, 2);
2392 WSET (packet
, smb_vwv4
, 0); /* server->pid */
2393 DSET (packet
, smb_vwv5
, server
->sesskey
);
2394 WSET (packet
, smb_vwv7
, password_len
);
2395 WSET (packet
, smb_vwv8
, 0);
2396 WSET (packet
, smb_vwv9
, 0);
2398 p
= SMB_BUF (packet
);
2399 memcpy (p
, server
->mount_data
.password
, password_len
);
2401 memcpy (p
, server
->mount_data
.username
, user_len
);
2404 if ((result
= smb_request_ok (server
, SMBsesssetupX
, 3, 0)) < 0)
2406 LOG (("smb_proc_connect: SMBsessetupX failed\n"));
2410 smb_decode_word (packet
+ 32, &(server
->server_uid
));
2415 server
->blkmode
= 0;
2416 server
->sesskey
= 0;
2418 password_len
= strlen(server
->mount_data
.password
)+1;
2420 nt_password_len
= 0;
2423 if(nt_password_len
> 0)
2425 strlcpy(full_share
,"//",sizeof(full_share
));
2426 strlcat(full_share
,server
->mount_data
.server_name
,sizeof(full_share
));
2427 strlcat(full_share
,"/",sizeof(full_share
));
2428 strlcat(full_share
,server
->mount_data
.service
,sizeof(full_share
));
2430 full_share_len
= strlen(full_share
);
2432 for(i
= 0 ; i
< full_share_len
; i
++)
2434 if(full_share
[i
] == '/')
2435 full_share
[i
] = '\\';
2438 StringToUpper(full_share
);
2440 SHOWSTRING(full_share
);
2442 memset (packet
, 0, SMB_HEADER_LEN
);
2444 smb_setup_header (server
, SMBtconX
, 4, password_len
+ full_share_len
+1 + strlen(dev
)+1);
2446 WSET (packet
, smb_vwv0
, 0xFF);
2447 WSET (packet
, smb_vwv3
, password_len
);
2449 p
= SMB_BUF (packet
);
2451 if(nt_password_len
> 0)
2452 memcpy(p
,password
,password_len
);
2454 memcpy (p
, server
->mount_data
.password
, password_len
);
2458 memcpy(p
,full_share
,full_share_len
+1);
2459 p
+= full_share_len
+1;
2463 BSET(packet
,smb_rcls
,1);
2465 if ((result
= smb_request_ok (server
, SMBtconX
, 3, 0)) < 0)
2467 SHOWVALUE(SMB_WCT(packet
));
2469 LOG (("smb_proc_connect: SMBtconX not verified.\n"));
2473 SHOWVALUE(SMB_WCT(packet
));
2475 /* Changed, max_xmit hasn't been updated if a tconX message was send instead of tcon. */
2477 server
->max_xmit
= server
->maxxmt
;
2479 server
->tid
= WVAL(packet
,smb_tid
);
2483 /* Fine! We have a connection, send a tcon message. */
2484 smb_setup_header (server
, SMBtcon
, 0, 6 + strlen (server
->mount_data
.service
) + strlen (server
->mount_data
.password
) + strlen (dev
));
2486 p
= SMB_BUF (packet
);
2487 p
= smb_encode_ascii (p
, server
->mount_data
.service
, strlen (server
->mount_data
.service
));
2488 p
= smb_encode_ascii (p
, server
->mount_data
.password
, strlen (server
->mount_data
.password
));
2489 (void) smb_encode_ascii (p
, dev
, strlen (dev
));
2491 if ((result
= smb_request_ok (server
, SMBtcon
, 2, 0)) < 0)
2493 LOG (("smb_proc_connect: SMBtcon not verified.\n"));
2497 LOG (("OK! Managed to set up SMBtcon!\n"));
2499 p
= SMB_VWV (packet
);
2500 p
= smb_decode_word (p
, &server
->max_xmit
);
2502 SHOWVALUE(server
->max_xmit
);
2504 /* Added by Brian Willette - We were ignoring the server's initial
2506 if (server
->maxxmt
!= 0 && server
->max_xmit
> server
->maxxmt
)
2507 server
->max_xmit
= server
->maxxmt
;
2509 (void) smb_decode_word (p
, &server
->tid
);
2512 SHOWVALUE(server
->max_xmit
);
2514 /* Changed, max_xmit hasn't been updated if a tconX message was send instead of tcon. */
2515 if (server
->max_xmit
> given_max_xmit
)
2516 server
->max_xmit
= given_max_xmit
;
2518 /* Ok, everything is fine. max_xmit does not include
2519 the TCP-SMB header of 4 bytes. */
2520 if (server
->max_xmit
< 65535 - 4)
2521 server
->max_xmit
+= 4;
2523 LOG (("max_xmit = %ld, tid = %ld\n", server
->max_xmit
, server
->tid
));
2525 LOG (("smb_proc_connect: Normal exit\n"));
2531 server
->state
= CONN_INVALID
;
2536 /* smb_proc_reconnect: server->packet is allocated with
2537 server->max_xmit bytes if and only if we return >= 0 */
2539 smb_proc_connect (struct smb_server
*server
)
2543 result
= smb_proc_reconnect (server
);
2545 if ((result
< 0) && (server
->packet
!= NULL
))
2547 free (server
->packet
);
2548 server
->packet
= NULL
;
2554 /* error code stuff - put together by Merik Karman
2555 merik -at- blackadder -dot- dsh -dot- oz -dot- au */
2563 /* Dos Error Messages */
2564 static const err_code_struct dos_msgs
[] =
2566 {"ERRbadfunc", 1, "Invalid function"},
2567 {"ERRbadfile", 2, "File not found"},
2568 {"ERRbadpath", 3, "Directory invalid"},
2569 {"ERRnofids", 4, "No file descriptors available"},
2570 {"ERRnoaccess", 5, "Access denied"},
2571 {"ERRbadfid", 6, "Invalid file handle"},
2572 {"ERRbadmcb", 7, "Memory control blocks destroyed"},
2573 {"ERRnomem", 8, "Insufficient server memory to perform the requested function"},
2574 {"ERRbadmem", 9, "Invalid memory block address"},
2575 {"ERRbadenv", 10, "Invalid environment"},
2576 {"ERRbadformat", 11, "Invalid format"},
2577 {"ERRbadaccess", 12, "Invalid open mode"},
2578 {"ERRbaddata", 13, "Invalid data"},
2579 {"ERR", 14, "reserved"},
2580 {"ERRbaddrive", 15, "Invalid drive specified"},
2581 {"ERRremcd", 16, "A Delete Directory request attempted to remove the server's current directory"},
2582 {"ERRdiffdevice", 17, "Not same device"},
2583 {"ERRnofiles", 18, "A File Search command can find no more files matching the specified criteria"},
2584 {"ERRbadshare", 32, "The sharing mode specified for an Open conflicts with existing FIDs on the file"},
2585 {"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"},
2586 {"ERRfilexists", 80, "The file named in a Create Directory, Make New File or Link request already exists"},
2587 {"ERRbadpipe", 230, "Pipe invalid"},
2588 {"ERRpipebusy", 231, "All instances of the requested pipe are busy"},
2589 {"ERRpipeclosing", 232, "Pipe close in progress"},
2590 {"ERRnotconnected", 233, "No process on other end of pipe"},
2591 {"ERRmoredata", 234, "There is more data to be returned"},
2596 /* Server Error Messages */
2597 static const err_code_struct server_msgs
[] =
2599 {"ERRerror", 1, "Non-specific error code"},
2600 {"ERRbadpw", 2, "Bad password - name/password pair in a Tree Connect or Session Setup are invalid"},
2601 {"ERRbadtype", 3, "reserved"},
2602 {"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"},
2603 {"ERRinvnid", 5, "The tree ID (TID) specified in a command was invalid"},
2604 {"ERRinvnetname", 6, "Invalid network name in tree connect"},
2605 {"ERRinvdevice", 7, "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection"},
2606 {"ERRqfull", 49, "Print queue full (files) -- returned by open print file"},
2607 {"ERRqtoobig", 50, "Print queue full -- no space"},
2608 {"ERRqeof", 51, "EOF on print queue dump"},
2609 {"ERRinvpfid", 52, "Invalid print file FID"},
2610 {"ERRsmbcmd", 64, "The server did not recognize the command received"},
2611 {"ERRsrverror", 65, "The server encountered an internal error, e.g., system file unavailable"},
2612 {"ERRfilespecs", 67, "The file handle (FID) and pathname parameters contained an invalid combination of values"},
2613 {"ERRreserved", 68, "reserved"},
2614 {"ERRbadpermits", 69, "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute"},
2615 {"ERRreserved", 70, "reserved"},
2616 {"ERRsetattrmode", 71, "The attribute mode in the Set File Attribute request is invalid"},
2617 {"ERRpaused", 81, "Server is paused"},
2618 {"ERRmsgoff", 82, "Not receiving messages"},
2619 {"ERRnoroom", 83, "No room to buffer message"},
2620 {"ERRrmuns", 87, "Too many remote user names"},
2621 {"ERRtimeout", 88, "Operation timed out"},
2622 {"ERRnoresource", 89, "No resources currently available for request"},
2623 {"ERRtoomanyuids", 90, "Too many UIDs active on this session"},
2624 {"ERRbaduid", 91, "The UID is not known as a valid ID on this session"},
2625 {"ERRusempx", 250, "Temp unable to support Raw, use MPX mode"},
2626 {"ERRusestd", 251, "Temp unable to support Raw, use standard read/write"},
2627 {"ERRcontmpx", 252, "Continue in MPX mode"},
2628 {"ERRreserved", 253, "reserved"},
2629 {"ERRreserved", 254, "reserved"},
2630 {"ERRnosupport", 0xFFFF, "Function not supported"},
2635 /* Hard Error Messages */
2636 static const err_code_struct hard_msgs
[] =
2638 {"ERRnowrite", 19, "Attempt to write on write-protected diskette"},
2639 {"ERRbadunit", 20, "Unknown unit"},
2640 {"ERRnotready", 21, "Drive not ready"},
2641 {"ERRbadcmd", 22, "Unknown command"},
2642 {"ERRdata", 23, "Data error (CRC)"},
2643 {"ERRbadreq", 24, "Bad request structure length"},
2644 {"ERRseek", 25, "Seek error"},
2645 {"ERRbadmedia", 26, "Unknown media type"},
2646 {"ERRbadsector", 27, "Sector not found"},
2647 {"ERRnopaper", 28, "Printer out of paper"},
2648 {"ERRwrite", 29, "Write fault"},
2649 {"ERRread", 30, "Read fault"},
2650 {"ERRgeneral", 31, "General failure"},
2651 {"ERRbadshare", 32, "A open conflicts with an existing open"},
2652 {"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"},
2653 {"ERRwrongdisk", 34, "The wrong disk was found in a drive"},
2654 {"ERRFCBUnavail", 35, "No FCBs are available to process request"},
2655 {"ERRsharebufexc", 36, "A sharing buffer has been exceeded"},
2664 const err_code_struct
*err_msgs
;
2667 static const err_class_struct err_classes
[] =
2669 { 0, "SUCCESS", NULL
},
2670 { 0x01, "ERRDOS", dos_msgs
},
2671 { 0x02, "ERRSRV", server_msgs
},
2672 { 0x03, "ERRHRD", hard_msgs
},
2673 { 0x04, "ERRXOS", NULL
},
2674 { 0xE1, "ERRRMX1", NULL
},
2675 { 0xE2, "ERRRMX2", NULL
},
2676 { 0xE3, "ERRRMX3", NULL
},
2677 { 0xFF, "ERRCMD", NULL
},
2683 smb_printerr (int class, int num
)
2686 err_code_struct
*err
;
2688 for (i
= 0; err_classes
[i
].class; i
++)
2690 if (err_classes
[i
].code
!= class)
2693 if (!err_classes
[i
].err_msgs
)
2695 ReportError("%s - %ld.", err_classes
[i
].class, num
);
2697 LOG (("%s - %ld\n", err_classes
[i
].class, num
));
2701 err
= (err_code_struct
*)err_classes
[i
].err_msgs
;
2703 for (j
= 0; err
[j
].name
; j
++)
2705 if (num
!= err
[j
].code
)
2708 ReportError ("%s - %s (%s).", err_classes
[i
].class, err
[j
].name
, err
[j
].message
);
2710 LOG (("%s - %s (%s)\n",err_classes
[i
].class, err
[j
].name
,err
[j
].message
));
2715 ReportError ("Unknown error - (%ld, %ld).", class, num
);
2717 LOG (("Unknown error - (%ld, %ld)\n", class, num
));