Corrections to SVN properties.
[AROS.git] / workbench / network / smbfs / source_code / proc.c
blob56f8995d2d26283bfdfb3d5273297487409db4f4
1 /*
2 * $Id$
4 * :ts=8
6 * proc.c
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>
16 #include "smbfs.h"
17 #if !defined(__AROS__)
18 #include "quad_math.h"
19 #endif
21 /*****************************************************************************/
23 #include <smb/smb.h>
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 *****************************************************************************/
73 static INLINE byte *
74 smb_encode_word (byte * p, word data)
76 p[0] = data & 0x00ffU;
77 p[1] = (data & 0xff00U) >> 8;
78 return &p[2];
81 static INLINE byte *
82 smb_decode_word (byte * p, word * data)
84 (*data) = (word) p[0] | p[1] << 8;
85 return &(p[2]);
88 byte *
89 smb_encode_smb_length (byte * p, dword len)
91 p[0] = p[1] = 0;
92 p[2] = (len & 0xFF00) >> 8;
93 p[3] = (len & 0xFF);
95 if (len > 0xFFFF)
96 p[1] |= 0x01;
98 return &p[4];
101 static byte *
102 smb_encode_dialect (byte * p, const byte * name, int len)
104 (*p++) = 2;
105 strcpy (p, name);
107 return p + len + 1;
110 static byte *
111 smb_encode_ascii (byte * p, const byte * name, int len)
113 (*p++) = 4;
114 strcpy (p, name);
116 return p + len + 1;
119 static void
120 smb_encode_vblock (byte * p, const byte * data, word len, int unused_fs)
122 (*p++) = 5;
123 p = smb_encode_word (p, len);
124 memcpy (p, data, len);
127 static byte *
128 smb_decode_data (byte * p, byte * data, word * data_len, int unused_fs)
130 word len;
132 if (!((*p) == 1 || (*p) == 5))
133 LOG (("Warning! Data block not starting with 1 or 5\n"));
135 len = WVAL (p, 1);
136 p += 3;
138 memcpy (data, p, len);
140 (*data_len) = len;
142 return p + len;
145 static byte *
146 smb_name_mangle (byte * p, const byte * name)
148 int len, pad = 0;
150 len = strlen (name);
152 if (len < 16)
153 pad = 16 - len;
155 (*p++) = 2 * (len + pad);
157 while ((*name) != '\0')
159 (*p++) = ((*name) >> 4) + 'A';
160 (*p++) = ((*name) & 0x0F) + 'A';
162 name++;
165 while (pad-- > 0)
167 (*p++) = 'C';
168 (*p++) = 'A';
171 (*p++) = '\0';
173 return p;
176 /* According to the core protocol documentation times are
177 expressed as seconds past January 1st, 1970, local
178 time zone. */
179 static INLINE int
180 utc2local (int time_value)
182 int result;
184 if(time_value > 0)
185 result = time_value - GetTimeZoneDelta();
186 else
187 result = time_value;
189 return result;
192 static INLINE int
193 local2utc (int time_value)
195 int result;
197 if(time_value > 0)
198 result = time_value + GetTimeZoneDelta();
199 else
200 result = time_value;
202 return result;
205 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since January 1st 1970). */
206 static int
207 date_dos2unix (unsigned short time_value, unsigned short date)
209 time_t seconds;
210 struct tm tm;
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);
223 return(seconds);
226 /* Convert linear UNIX date to a MS-DOS time/date pair. */
227 static void
228 date_unix2dos (int unix_date, unsigned short *time_value, unsigned short *date)
230 struct tm tm;
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 /****************************************************************************
240 * Support section.
242 ****************************************************************************/
243 dword
244 smb_len (byte * packet)
246 return (dword)( (((dword)(packet[1] & 0x1)) << 16) | (((dword)packet[2]) << 8) | (packet[3]) );
249 static INLINE word
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 */
259 static INLINE int
260 smb_valid_packet (byte * packet)
262 int result;
264 LOG (("len: %ld, wct: %ld, bcc: %ld -- SMB_HEADER_LEN[%ld] + SMB_WCT (packet) * 2[%ld] + SMB_BCC (packet)[%ld] + 2 = %ld\n",
265 smb_len (packet),
266 SMB_WCT (packet),
267 SMB_BCC (packet),
268 SMB_HEADER_LEN,
269 SMB_WCT (packet) * 2,
270 SMB_BCC (packet),
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
278 && packet[5] == 'S'
279 && packet[6] == 'M'
280 && packet[7] == 'B'
281 && (smb_len (packet) + 4 >= (dword)
282 (SMB_HEADER_LEN + SMB_WCT (packet) * 2 + SMB_BCC (packet) + 2))) ? 0 : (-EIO);
284 return result;
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. */
289 static INLINE int
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;
297 static int
298 smb_errno (int errcls, int error)
300 int result,i;
302 if (errcls)
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 },
314 { ERRbadfid,EBADF },
315 { ERRbadmcb,EIO },
316 { ERRnomem,ENOMEM },
317 { ERRbadmem,EFAULT },
318 { ERRbadenv,EIO },
319 { ERRbadformat,EIO },
320 { ERRbadaccess,EACCES },
321 { ERRbaddata,E2BIG },
322 { ERRbaddrive,ENXIO },
323 { ERRremcd,EIO },
324 { ERRdiffdevice,EXDEV },
325 { ERRnofiles,0 },
326 { ERRbadshare,ETXTBSY },
327 { ERRlock,EDEADLK },
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 */
332 { -1,-1 }
335 result = EIO;
337 for(i = 0 ; map[i][0] != -1 ; i++)
339 if(map[i][0] == error)
341 result = map[i][1];
342 break;
346 else if (errcls == ERRSRV)
348 static const int map[][2] =
350 { ERRerror,ENFILE },
351 { ERRbadpw,EINVAL },
352 { ERRbadtype,EIO },
353 { ERRaccess,EACCES },
354 { -1, -1 }
357 result = EIO;
359 for(i = 0 ; map[i][0] != -1 ; i++)
361 if(map[i][0] == error)
363 result = map[i][1];
364 break;
368 else if (errcls == ERRHRD)
370 static const int map[][2] =
372 { ERRnowrite,EROFS },
373 { ERRbadunit,ENODEV },
374 { ERRnotready,EBUSY },
375 { ERRbadcmd,EIO },
376 { ERRdata,EIO },
377 { ERRbadreq,ERANGE },
378 { ERRbadshare,ETXTBSY },
379 { ERRlock,EDEADLK },
380 { -1, -1 }
383 result = EIO;
385 for(i = 0 ; map[i][0] != -1 ; i++)
387 if(map[i][0] == error)
389 result = map[i][1];
390 break;
394 else if (errcls == ERRCMD)
396 result = EIO;
398 else
400 result = 0;
403 return(result);
406 #if DEBUG
408 static char
409 print_char (char c)
411 if ((c < ' ') || (c > '~'))
412 return '.';
414 return c;
417 static void
418 smb_dump_packet (byte * packet)
420 int i, j, len;
421 int errcls, error;
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));
430 if (errcls)
431 smb_printerr (errcls, error);
433 if (len > 100)
434 len = 100;
436 PRINTHEADER();
438 for (i = 0; i < len; i += 10)
440 PRINTF (("%03ld:", i));
442 for (j = i; j < i + 10; j++)
444 if (j < len)
445 PRINTF (("%02lx ", packet[j]));
446 else
447 PRINTF ((" "));
450 PRINTF ((": "));
452 for (j = i; j < i + 10; j++)
454 if (j < len)
455 PRINTF (("%lc", print_char (packet[j])));
458 PRINTF (("\n"));
462 #endif /* DEBUG */
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. */
468 static int
469 smb_request_ok (struct smb_server *s, int command, int wct, int bcc)
471 int result;
472 int error;
474 s->rcls = 0;
475 s->err = 0;
477 result = smb_request (s);
478 if (result < 0)
480 LOG (("smb_request failed\n"));
482 else if ((error = smb_valid_packet (s->packet)) != 0)
484 LOG (("not a valid packet!\n"));
485 result = error;
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"));
494 result = error;
497 return(result);
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
504 of any use. */
505 static int
506 smb_retry (struct smb_server *server)
508 int result = 0;
510 if (server->state == CONN_VALID)
511 goto out;
513 if (smb_release (server) < 0)
515 LOG (("smb_retry: smb_release failed\n"));
516 server->state = CONN_RETRIED;
517 goto out;
520 if (smb_proc_reconnect (server) < 0)
522 LOG (("smb_proc_reconnect failed\n"));
523 server->state = CONN_RETRIED;
524 goto out;
527 server->state = CONN_VALID;
528 result = 1;
530 out:
532 return result;
535 static int
536 smb_request_ok_unlock (struct smb_server *s, int command, int wct, int bcc)
538 int result;
540 result = smb_request_ok (s, command, wct, bcc);
542 return result;
545 /* smb_setup_header: We completely set up the packet. You only have to
546 insert the command-specific fields */
547 static byte *
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); */
560 BSET (p, 0, 0xff);
561 BSET (p, 1, 'S');
562 BSET (p, 2, 'M');
563 BSET (p, 3, 'B');
564 BSET (p, 4, command);
566 p += 5;
567 memset (p, '\0', 19);
568 p += 19;
569 p += 8;
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 */
583 p += 2 * wct;
584 WSET (p, 0, bcc);
586 return p + 2;
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! */
592 static byte *
593 smb_setup_header_exclusive (struct smb_server *server, byte command, word wct, word bcc)
595 byte * result;
597 result = smb_setup_header (server, command, wct, bcc);
599 return result;
602 /*****************************************************************************
604 * File operation section.
606 ****************************************************************************/
609 smb_proc_open (struct smb_server *server, const char *pathname, int len, struct smb_dirent *entry)
611 int error;
612 char *p;
613 char *buf = server->packet;
614 const word o_attr = aSYSTEM | aHIDDEN | aDIR;
616 LOG (("path=%s\n", pathname));
618 retry:
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))
628 goto retry;
630 if (error != -EACCES)
631 goto out;
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))
641 goto retry;
643 goto out;
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);
652 entry->opened = 1;
654 #if DEBUG
656 struct tm tm;
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));
670 #endif /* DEBUG */
672 out:
674 return error;
677 /* smb_proc_close: in finfo->mtime we can send a modification time to
678 the server */
680 smb_proc_close (struct smb_server *server, word fileid, dword mtime)
682 char *buf = server->packet;
683 int local_time;
684 int result;
686 if(mtime != 0 && mtime != 0xffffffff)
688 /* 0 and 0xffffffff mean: do not set mtime */
689 local_time = utc2local (mtime);
691 else
693 local_time = 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);
702 return result;
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
709 memcpy_tofs. */
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;
715 int result;
716 int error;
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)
727 result = error;
728 goto out;
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));
740 else
742 LOG (("ret_c=%ld, data_len=%ld\n", returned_count, data_len));
745 result = data_len;
747 out:
749 return result;
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
754 call. */
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;
759 int result;
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);
771 return result;
775 smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data)
777 int res;
778 char *buf = server->packet;
779 byte *p;
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);
787 (*p++) = 1;
788 WSET (p, 0, count);
789 memcpy (p + 2, data, count);
791 if ((res = smb_request_ok (server, SMBwrite, 1, 0)) >= 0)
792 res = WVAL (buf, smb_vwv0);
794 return res;
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;
802 int result;
803 long len = server->max_xmit - 4;
804 byte *p;
806 if (len >= count)
807 len = 0;
808 else
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));
826 if (len > 0)
827 memcpy (p, data, len);
829 result = smb_request_ok (server, SMBwritebraw, 1, 0);
831 LOG (("first request returned %ld\n", result));
833 if (result < 0)
834 goto out;
836 result = smb_request_write_raw (server, data + len, count - len);
838 LOG(("raw request returned %ld\n", result));
840 if (result > 0)
842 int error;
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"));
848 result = error;
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"));
857 result = error;
860 /* If everything went fine, the whole block has been transfered. */
861 if (result == (count - len))
862 result = count;
865 out:
867 return result;
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;
874 int error;
876 retry:
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))
887 goto retry;
889 else
891 (*new_position_ptr) = DVAL(buf, smb_vwv0);
894 return error;
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)
901 int result;
902 int num_locks, num_unlocks;
903 char *buf = server->packet;
904 char *data;
905 struct smb_lkrng *p;
906 int i;
908 num_locks = num_unlocks = 0;
910 if (mode & 2)
911 num_unlocks = num_entries;
912 else
913 num_locks = num_entries;
915 retry:
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))
937 goto retry;
940 return result;
943 /* smb_proc_do_create: We expect entry->attry & entry->ctime to be set. */
944 static int
945 smb_proc_do_create (struct smb_server *server, const char *path, int len, struct smb_dirent *entry, word command)
947 int error;
948 char *p;
949 char *buf = server->packet;
950 int local_time;
952 retry:
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))
963 goto retry;
965 goto out;
968 entry->opened = 1;
969 entry->fileid = WVAL (buf, smb_vwv0);
971 smb_proc_close (server, entry->fileid, entry->mtime);
973 out:
975 return error;
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)
987 char *p;
988 char *buf = server->packet;
989 int result;
991 retry:
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))
1003 goto retry;
1006 return result;
1010 smb_proc_mkdir (struct smb_server *server, const char *path, const int len)
1012 char *p;
1013 int result;
1015 retry:
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))
1024 goto retry;
1027 return result;
1031 smb_proc_rmdir (struct smb_server *server, const char *path, const int len)
1033 char *p;
1034 int result;
1036 retry:
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))
1045 goto retry;
1048 return result;
1052 smb_proc_unlink (struct smb_server *server, const char *path, const int len)
1054 char *p;
1055 char *buf = server->packet;
1056 int result;
1058 retry:
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))
1069 goto retry;
1072 return result;
1076 smb_proc_trunc (struct smb_server *server, word fid, dword length)
1078 char *p;
1079 char *buf = server->packet;
1080 int result;
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);
1090 if (result >= 0)
1091 result = DVAL(buf, smb_vwv0);
1093 return result;
1096 static char *
1097 smb_decode_dirent (char *p, struct smb_dirent *entry)
1099 size_t name_size;
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);
1107 name_size = 13;
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));
1118 #if DEBUG
1120 struct tm tm;
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));
1134 #endif /* DEBUG */
1136 return p + 22;
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 */
1141 static int
1142 smb_proc_readdir_short (struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry)
1144 char *p;
1145 char *buf;
1146 int error;
1147 int result = 0;
1148 int i;
1149 int first, total_count;
1150 struct smb_dirent *current_entry;
1151 word bcc;
1152 word count;
1153 char status[SMB_STATUS_SIZE];
1154 int entries_asked = (server->max_xmit - 100) / SMB_DIRINFO_SIZE;
1155 int dirlen = strlen (path);
1156 char * mask;
1158 mask = malloc(dirlen + 4 + 1);
1159 if (mask == NULL)
1161 result = (-ENOMEM);
1162 goto out;
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;
1173 retry:
1175 first = 1;
1176 total_count = 0;
1177 current_entry = entry;
1179 while (1)
1181 if (first == 1)
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));
1187 (*p++) = 5;
1188 (void) smb_encode_word (p, 0);
1190 else
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;
1204 goto unlock_return;
1206 else
1208 if (smb_retry (server))
1209 goto retry;
1211 result = error;
1213 goto unlock_return;
1217 p = SMB_VWV (server->packet);
1218 p = smb_decode_word (p, &count); /* vwv[0] = count-returned */
1219 p = smb_decode_word (p, &bcc);
1221 first = 0;
1223 if (count <= 0)
1225 result = total_count - fpos;
1227 goto unlock_return;
1230 if (bcc != count * SMB_DIRINFO_SIZE + 3)
1232 result = -EIO;
1234 goto unlock_return;
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;
1256 goto unlock_return;
1258 else
1260 p = smb_decode_dirent (p, current_entry);
1262 current_entry += 1;
1265 total_count += 1;
1269 unlock_return:
1271 if(mask != NULL)
1272 free(mask);
1274 out:
1276 return result;
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.
1289 static time_t
1290 interpret_long_date(char * p)
1292 QUAD adjust;
1293 QUAD long_date;
1294 ULONG underflow;
1295 time_t result;
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;
1318 else
1319 result = 0;
1321 return(result);
1323 #else
1324 static time_t
1325 interpret_long_date(char * p)
1327 UQUAD long_date;
1328 int sectime;
1330 long_date = *(UQUAD *)p - (0x2B6109100ULL * 10000000);
1331 sectime = long_date / 10000000;
1333 return((time_t)sectime);
1335 #endif
1337 /*****************************************************************************/
1339 static void
1340 smb_get_dirent_name(char *p,int level,char ** name_ptr,int * len_ptr)
1342 switch (level)
1344 case 1: /* OS/2 understands this */
1345 (*name_ptr) = p + 27;
1346 (*len_ptr) = strlen(p + 27);
1347 break;
1349 case 2: /* this is what OS/2 uses */
1350 (*name_ptr) = p + 31;
1351 (*len_ptr) = strlen(p + 31);
1352 break;
1354 case 3: /* untested */
1355 (*name_ptr) = p + 33;
1356 (*len_ptr) = strlen(p + 33);
1357 break;
1359 case 4: /* untested */
1360 (*name_ptr) = p + 37;
1361 (*len_ptr) = strlen(p + 37);
1362 break;
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);
1367 break;
1369 default:
1370 (*name_ptr) = NULL;
1371 (*len_ptr) = 0;
1372 break;
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
1379 is used by OS/2. */
1380 static char *
1381 smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level)
1383 char *result;
1385 switch (level)
1387 case 1: /* OS/2 understands this */
1389 #if DEBUG
1391 char buffer[255];
1393 memcpy(buffer,p + 27,sizeof(buffer)-1);
1394 buffer[sizeof(buffer)-1] = '\0';
1396 LOG(("type=%ld, name='%s'\n",level,buffer));
1398 #endif /* DEBUG */
1400 if (finfo != NULL)
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;
1411 #if DEBUG
1413 struct tm tm;
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));
1427 #endif /* DEBUG */
1430 result = p + 28 + BVAL (p, 26);
1432 break;
1434 case 2: /* this is what OS/2 uses */
1436 #if DEBUG
1438 char buffer[255];
1440 memcpy(buffer,p + 31,sizeof(buffer)-1);
1441 buffer[sizeof(buffer)-1] = '\0';
1443 LOG(("type=%ld, name='%s'\n",level,buffer));
1445 #endif /* DEBUG */
1447 if (finfo != NULL)
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;
1458 #if DEBUG
1460 struct tm tm;
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));
1474 #endif /* DEBUG */
1477 result = p + 32 + BVAL (p, 30);
1479 break;
1481 case 260: /* NT uses this, but also accepts 2 */
1483 #if DEBUG
1485 char buffer[255];
1486 int len;
1488 len = min (DVAL (p+60, 0), sizeof(buffer)-1);
1490 memcpy(buffer,p+94,len);
1491 buffer[len] = '\0';
1493 LOG(("type=%ld, name='%s'\n",level,buffer));
1495 #endif /* DEBUG */
1497 result = p + WVAL (p, 0);
1499 if (finfo != NULL)
1501 int namelen;
1502 time_t swap;
1504 p += 4; /* next entry offset */
1505 p += 4; /* fileindex */
1506 finfo->ctime = interpret_long_date(p);
1507 p += 8;
1508 finfo->atime = interpret_long_date(p);
1509 p += 8;
1510 finfo->wtime = interpret_long_date(p);
1511 p += 8;
1512 finfo->mtime = interpret_long_date(p);
1513 p += 8;
1514 finfo->size = DVAL (p, 0);
1515 p += 8;
1516 p += 8; /* alloc size */
1517 finfo->attr = BVAL (p, 0);
1518 p += 4;
1519 namelen = min (DVAL (p, 0), SMB_MAXNAMELEN);
1520 p += 4;
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;
1542 #if DEBUG
1544 struct tm tm;
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));
1558 #endif /* DEBUG */
1561 break;
1563 default:
1565 if (finfo != NULL)
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);
1576 break;
1579 return result;
1582 static int
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;
1590 char *p;
1591 int i;
1592 int first;
1593 int total_count = 0;
1594 struct smb_dirent *current_entry;
1596 char *resp_data;
1597 char *resp_param;
1598 int resp_data_len = 0;
1599 int resp_param_len = 0;
1601 int attribute = aSYSTEM | aHIDDEN | aDIR;
1602 int result;
1603 int error = 0;
1605 int ff_searchcount;
1606 int ff_eos = 0;
1607 int ff_dir_handle = 0;
1608 int ff_resume_key = 0;
1609 int loop_count = 0;
1611 unsigned char *outbuf = server->packet;
1613 int dirlen = strlen (path) + 2 + 1;
1614 char *mask;
1615 int masklen;
1617 ENTER();
1619 /* ZZZ experimental 'max_matches' adjustment */
1621 if(info_level == 260)
1622 max_matches = server->max_xmit / 360;
1623 else
1624 max_matches = server->max_xmit / 40;
1627 SHOWVALUE(server->max_xmit);
1628 SHOWVALUE(max_matches);
1630 mask = malloc (dirlen);
1631 if (mask == NULL)
1633 LOG (("Memory allocation failed\n"));
1634 error = (-ENOMEM);
1635 SHOWVALUE(error);
1636 goto out;
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));
1646 resp_param = NULL;
1647 resp_data = NULL;
1649 retry:
1651 first = 1;
1652 total_count = 0;
1653 current_entry = entry;
1655 while (ff_eos == 0)
1657 loop_count++;
1658 if (loop_count > 200)
1660 LOG (("smb_proc_readdir_long: Looping in FIND_NEXT???\n"));
1661 error = -EIO;
1662 SHOWVALUE(error);
1663 break;
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 */
1686 (*p++) = 'D';
1687 (*p++) = ' '; /* this was added because OS/2 does it */
1689 if (first != 0)
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);
1696 DSET (p, 8, 0);
1698 else
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 */
1708 p += 12;
1710 if(masklen > 0)
1711 memcpy (p, mask, masklen);
1713 p += masklen;
1714 (*p++) = 0;
1715 (*p) = 0;
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));
1721 if (result < 0)
1723 if (smb_retry (server))
1724 goto retry;
1726 LOG (("smb_proc_readdir_long: got error from trans2_request\n"));
1727 error = result;
1728 SHOWVALUE(error);
1729 break;
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);
1741 continue;
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);
1748 SHOWVALUE(error);
1749 break;
1752 /* ZZZ bail out if this is empty. */
1753 if (resp_param == NULL)
1754 break;
1756 /* parse out some important return info */
1757 p = resp_param;
1758 if (first != 0)
1760 ff_dir_handle = WVAL (p, 0);
1761 ff_searchcount = WVAL (p, 2);
1762 ff_eos = WVAL (p, 4);
1764 else
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)
1772 break;
1774 /* ZZZ bail out if this is empty. */
1775 if (resp_data == NULL)
1776 break;
1778 /* point to the data bytes */
1779 p = resp_data;
1781 /* Now we are ready to parse smb directory entries. */
1782 for (i = 0; i < ff_searchcount; i++)
1784 if(i == ff_searchcount - 1)
1786 char * last_name;
1787 int len;
1789 ff_resume_key = DVAL(p, 0);
1791 smb_get_dirent_name(p,info_level,&last_name,&len);
1792 if(len > 0)
1794 #if DEBUG
1796 char buffer[SMB_MAXNAMELEN+1];
1798 memcpy(buffer,last_name,len);
1799 buffer[len] = '\0';
1801 LOG(("last name = '%s'\n",buffer));
1803 #endif /* DEBUG */
1805 if(len + 1 > dirlen)
1807 D(("increasing mask; old value = %ld new value = %ld",dirlen,len+1));
1809 if(mask != NULL)
1810 free (mask);
1812 dirlen = len + 1;
1813 SHOWVALUE(dirlen);
1815 mask = malloc (dirlen);
1816 if (mask == NULL)
1818 LOG (("smb_proc_readdir_long: Memory allocation failed\n"));
1820 error = -ENOMEM;
1822 SHOWVALUE(error);
1824 goto fail;
1828 memcpy (mask, last_name, len);
1829 mask[len] = '\0';
1830 masklen = len;
1832 else
1834 masklen = 0;
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));
1850 continue;
1852 else
1854 p = smb_decode_long_dirent (p, current_entry, info_level);
1856 current_entry += 1;
1859 total_count += 1;
1862 SHOWVALUE(ff_resume_key);
1864 if (resp_data != NULL)
1866 free (resp_data);
1867 resp_data = NULL;
1870 if (resp_param != NULL)
1872 free (resp_param);
1873 resp_param = NULL;
1876 first = 0;
1878 if (ff_searchcount > 0)
1879 loop_count = 0;
1882 fail:
1884 /* finished: not needed any more */
1885 if (mask != NULL)
1886 free (mask);
1888 if (resp_data != NULL)
1889 free (resp_data);
1891 if (resp_param != NULL)
1892 free (resp_param);
1894 out:
1896 if(error < 0)
1898 RETURN(error);
1899 return(error);
1901 else
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)
1911 int result;
1913 if (server->protocol >= PROTOCOL_LANMAN2)
1914 result = smb_proc_readdir_long (server, path, fpos, cache_size, entry);
1915 else
1916 result = smb_proc_readdir_short (server, path, fpos, cache_size, entry);
1918 return result;
1922 smb_proc_getattr_core (struct smb_server *server, const char *path, int len, struct smb_dirent *entry)
1924 int result;
1925 char *p;
1926 char *buf = server->packet;
1928 LOG (("smb_proc_getattr: %s\n", path));
1930 retry:
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))
1938 goto retry;
1940 goto out;
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);
1950 #if DEBUG
1952 struct tm tm;
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));
1966 #endif /* DEBUG */
1968 out:
1970 return result;
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;
1978 int result;
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)
1984 goto out;
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);
1993 #if DEBUG
1995 struct tm tm;
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));
2009 #endif /* DEBUG */
2011 out:
2013 return result;
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)
2021 char *p;
2022 char *buf = server->packet;
2023 int result;
2024 int local_time;
2026 retry:
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))
2040 goto retry;
2043 return result;
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;
2053 int result;
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);
2075 return result;
2079 smb_proc_dskattr (struct smb_server *server, struct smb_dskattr *attr)
2081 int error;
2082 char *p;
2084 retry:
2086 smb_setup_header (server, SMBdskattr, 0, 0);
2088 if ((error = smb_request_ok (server, SMBdskattr, 5, 0)) < 0)
2090 if (smb_retry (server))
2091 goto retry;
2093 goto out;
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);
2102 out:
2104 return error;
2107 /*****************************************************************************
2109 * Mount/umount operations.
2111 ****************************************************************************/
2112 struct smb_prots
2114 enum smb_protocol prot;
2115 const char *name;
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
2121 connected. */
2122 static int
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"},
2135 {-1, NULL}
2138 char dev[] = "A:";
2139 int i, plength;
2140 int max_xmit = 1024; /* Space needed for first request. */
2141 int given_max_xmit = server->mount_data.max_xmit;
2142 int result;
2143 word any_word;
2144 byte *p;
2145 unsigned char password[24];
2146 int password_len;
2147 unsigned char nt_password[24];
2148 int nt_password_len;
2149 unsigned char full_share[SMB_MAXNAMELEN+1];
2150 int full_share_len;
2151 byte *packet;
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"));
2159 goto fail;
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"));
2173 result = -ENOMEM;
2174 goto fail;
2177 packet = server->packet;
2179 server->max_xmit = max_xmit;
2181 /* Start with an RFC1002 session request packet. */
2182 p = packet + 4;
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"));
2194 goto fail;
2197 if (packet[0] != 0x82)
2199 LOG (("smb_proc_connect: Did not receive positive response (err = %lx)\n",packet[0]));
2201 #if DEBUG
2203 smb_dump_packet (packet);
2205 #endif /* DEBUG */
2207 result = -EIO;
2208 goto fail;
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);
2216 plength = 0;
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"));
2231 goto fail;
2234 LOG (("Verified!\n"));
2236 p = SMB_VWV (packet);
2237 p = smb_decode_word (p, &any_word);
2238 i = 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);
2262 else
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);
2283 password_len = 24;
2285 PRINTHEADER();
2286 PRINTF(("password: "));
2287 for(i = 0 ; i < 24 ; i++)
2288 PRINTF(("%02lx ",password[i]));
2289 PRINTF(("\n"));
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;
2297 PRINTHEADER();
2298 PRINTF(("nt_password: "));
2299 for(i = 0 ; i < 24 ; i++)
2300 PRINTF(("%02lx ",nt_password[i]));
2301 PRINTF(("\n"));
2303 PRINTHEADER();
2304 PRINTF(("crypt_key: "));
2305 for(i = 0 ; i < 8 ; i++)
2306 PRINTF(("%02lx ",server->crypt_key[i]));
2307 PRINTF(("\n"));
2309 else
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,"");
2322 password_len = 0;
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";
2336 #else
2337 char *OS_id = "AROS";
2338 #endif
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);
2360 p += password_len;
2362 memcpy (p, nt_password, nt_password_len);
2363 p += nt_password_len;
2365 else
2367 SHOWMSG("adding plain text password");
2369 memcpy (p, server->mount_data.password, password_len);
2370 p += password_len;
2373 memcpy (p, server->mount_data.username, user_len);
2374 p += user_len;
2376 strcpy (p, server->mount_data.workgroup_name);
2377 p += strlen (p) + 1;
2379 strcpy (p, OS_id);
2380 p += strlen (p) + 1;
2382 strcpy (p, client_id);
2384 else
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);
2400 p += 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"));
2407 goto fail;
2410 smb_decode_word (packet + 32, &(server->server_uid));
2412 else
2414 server->maxxmt = 0;
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);
2453 else
2454 memcpy (p, server->mount_data.password, password_len);
2456 p += password_len;
2458 memcpy(p,full_share,full_share_len+1);
2459 p += full_share_len+1;
2461 strcpy(p,dev);
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"));
2470 goto fail;
2473 SHOWVALUE(SMB_WCT(packet));
2475 /* Changed, max_xmit hasn't been updated if a tconX message was send instead of tcon. */
2476 if (server->maxxmt)
2477 server->max_xmit = server->maxxmt;
2479 server->tid = WVAL(packet,smb_tid);
2481 else
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"));
2494 goto fail;
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
2505 maxbuf value */
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"));
2527 return 0;
2529 fail:
2531 server->state = CONN_INVALID;
2533 return result;
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)
2541 int result;
2543 result = smb_proc_reconnect (server);
2545 if ((result < 0) && (server->packet != NULL))
2547 free (server->packet);
2548 server->packet = NULL;
2551 return result;
2554 /* error code stuff - put together by Merik Karman
2555 merik -at- blackadder -dot- dsh -dot- oz -dot- au */
2556 typedef struct
2558 char *name;
2559 int code;
2560 char *message;
2561 } err_code_struct;
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"},
2593 {NULL, -1, NULL}
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"},
2632 {NULL, -1, NULL}
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"},
2657 {NULL, -1, NULL}
2660 typedef struct
2662 int code;
2663 char *class;
2664 const err_code_struct *err_msgs;
2665 } err_class_struct;
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 },
2679 { -1, NULL, NULL }
2682 static void
2683 smb_printerr (int class, int num)
2685 int i, j;
2686 err_code_struct *err;
2688 for (i = 0; err_classes[i].class; i++)
2690 if (err_classes[i].code != class)
2691 continue;
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));
2698 return;
2701 err = (err_code_struct *)err_classes[i].err_msgs;
2703 for (j = 0; err[j].name; j++)
2705 if (num != err[j].code)
2706 continue;
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));
2711 return;
2715 ReportError ("Unknown error - (%ld, %ld).", class, num);
2717 LOG (("Unknown error - (%ld, %ld)\n", class, num));