This commit was manufactured by cvs2svn to create branch 'SAMBA_TNG'.
[Samba.git] / source / smbd / reply.c
blobb980663cd51b9e1ec183b9ab7535a44a8c4fcf60
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
27 #include "includes.h"
28 #include "rpc_client.h"
29 #include "trans2.h"
30 #include "nterr.h"
32 /* look in server.c for some explanation of these variables */
33 extern int Protocol;
34 extern int DEBUGLEVEL;
35 extern int max_send;
36 extern int max_recv;
37 extern char magic_char;
38 extern BOOL case_sensitive;
39 extern BOOL case_preserve;
40 extern BOOL short_case_preserve;
41 extern pstring sesssetup_user;
42 extern pstring global_myname;
43 extern fstring global_myworkgroup;
44 extern int global_oplock_break;
45 uint32 global_client_caps = 0;
46 unsigned int smb_echo_count = 0;
48 /****************************************************************************
49 report a possible attack via the password buffer overflow bug
50 ****************************************************************************/
52 static void overflow_attack(int len)
54 if (DEBUGLVL(0))
56 dbgtext("ERROR: Invalid password length %d.\n", len);
57 dbgtext("Your machine may be under attack by someone ");
58 dbgtext("attempting to exploit an old bug.\n");
59 dbgtext("Attack was from IP = %s.\n", client_addr());
61 exit_server("possible attack");
65 /****************************************************************************
66 reply to an special message
67 ****************************************************************************/
69 int reply_special(char *inbuf, char *outbuf)
71 int outsize = 4;
72 int msg_type = CVAL(inbuf, 0);
73 int msg_flags = CVAL(inbuf, 1);
74 pstring name1, name2;
75 extern fstring remote_machine;
76 extern fstring local_machine;
77 int len;
78 char name_type = 0;
80 *name1 = *name2 = 0;
82 memset(outbuf, '\0', smb_size);
84 smb_setlen(outbuf, 0);
86 DEBUG(20, ("NBT message\n"));
87 dump_data(20, inbuf, smb_len(inbuf));
89 switch (msg_type)
91 case 0x81: /* session request */
92 CVAL(outbuf, 0) = 0x82;
93 CVAL(outbuf, 3) = 0;
94 if (name_len(inbuf + 4) > 50 ||
95 name_len(inbuf + 4 + name_len(inbuf + 4)) > 50)
97 DEBUG(0,
98 ("Invalid name length in session request\n"));
99 return (0);
101 name_extract(inbuf, 4, name1);
102 name_extract(inbuf, 4 + name_len(inbuf + 4), name2);
103 DEBUG(2, ("netbios connect: name1=%s name2=%s\n",
104 name1, name2));
106 fstrcpy(remote_machine, name2);
107 remote_machine[15] = 0;
108 trim_string(remote_machine, " ", " ");
109 strlower(remote_machine);
111 fstrcpy(local_machine, name1);
112 len = strlen(local_machine);
113 if (len == 16)
115 name_type = local_machine[15];
116 local_machine[15] = 0;
118 trim_string(local_machine, " ", " ");
119 strlower(local_machine);
121 if (name_type == 'R')
123 /* We are being asked for a pathworks session ---
124 no thanks! */
125 CVAL(outbuf, 0) = 0x83;
126 break;
129 add_session_user(remote_machine);
131 reload_services(True);
132 reopen_logs();
134 if (lp_status(-1))
136 claim_connection(NULL, "", MAXSTATUS, True);
139 break;
141 case 0x89: /* session keepalive request
142 (some old clients produce this?) */
143 CVAL(outbuf, 0) = 0x85;
144 CVAL(outbuf, 3) = 0;
145 break;
147 case 0x82: /* positive session response */
148 case 0x83: /* negative session response */
149 case 0x84: /* retarget session response */
150 DEBUG(0, ("Unexpected session response\n"));
151 break;
153 case 0x85: /* session keepalive */
154 default:
155 return (0);
158 DEBUG(5, ("init msg_type=0x%x msg_flags=0x%x\n",
159 msg_type, msg_flags));
161 return (outsize);
165 /*******************************************************************
166 work out what error to give to a failed connection
167 ********************************************************************/
168 static int connection_error(char *inbuf, char *outbuf, int ecode)
170 if (ecode == ERRnoipc)
171 return (ERROR(ERRDOS, ERRnoipc));
173 return (ERROR(ERRSRV, ecode));
178 /****************************************************************************
179 parse a share descriptor string
180 ****************************************************************************/
181 static void parse_connect(char *p, char *service, char *user,
182 char *password, int *pwlen, char *dev)
184 char *p2;
186 DEBUG(4, ("parsing connect string %s\n", p));
188 p2 = strrchr(p, '\\');
189 if (p2 == NULL)
190 fstrcpy(service, p);
191 else
192 fstrcpy(service, p2 + 1);
194 p += strlen(p) + 2;
196 fstrcpy(password, p);
197 *pwlen = strlen(password);
199 p += strlen(p) + 2;
201 fstrcpy(dev, p);
203 *user = 0;
204 p = strchr(service, '%');
205 if (p != NULL)
207 *p = 0;
208 fstrcpy(user, p + 1);
212 /****************************************************************************
213 Reply to a tcon.
214 ****************************************************************************/
216 int reply_tcon(connection_struct * conn,
217 char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
219 BOOL doencrypt = SMBENCRYPT();
220 pstring service;
221 pstring user;
222 pstring password;
223 pstring dev;
224 int outsize = 0;
225 uint16 vuid = SVAL(inbuf, smb_uid);
226 int pwlen = 0;
227 int ecode = -1;
229 *service = *user = *password = *dev = 0;
231 parse_connect(smb_buf(inbuf) + 1, service, user, password, &pwlen,
232 dev);
235 * Ensure the user and password names are in UNIX codepage format.
238 dos_to_unix(user, True);
239 if (!doencrypt)
241 dos_to_unix(password, True);
244 map_nt_and_unix_username(global_myworkgroup, user, user, NULL);
246 conn = make_connection(service, user, global_myworkgroup, password,
247 pwlen, dev, vuid, &ecode);
249 if (!conn)
251 return (connection_error(inbuf, outbuf, ecode));
254 outsize = set_message(outbuf, 2, 0, True);
255 SSVAL(outbuf, smb_vwv0, max_recv);
256 SSVAL(outbuf, smb_vwv1, conn->cnum);
257 SSVAL(outbuf, smb_tid, conn->cnum);
259 DEBUG(3, ("tcon service=%s user=%s cnum=%d\n",
260 service, user, conn->cnum));
262 return (outsize);
266 /****************************************************************************
267 Reply to a tcon and X.
268 ****************************************************************************/
269 int reply_tcon_and_X(connection_struct * conn, char *inbuf, char *outbuf,
270 int length, int bufsize)
272 fstring service;
273 pstring user;
274 pstring password;
275 pstring devicename;
276 BOOL doencrypt = SMBENCRYPT();
277 int ecode = -1;
278 uint16 vuid = SVAL(inbuf, smb_uid);
279 int passlen = SVAL(inbuf, smb_vwv3);
280 char *path;
281 char *p;
283 *service = *user = *password = *devicename = 0;
285 /* we might have to close an old one */
286 if ((SVAL(inbuf, smb_vwv2) & 0x1) && conn)
288 close_cnum(conn, vuid);
291 if (passlen > MAX_PASS_LEN)
293 overflow_attack(passlen);
296 memcpy(password, smb_buf(inbuf), passlen);
297 password[passlen] = 0;
298 path = smb_buf(inbuf) + passlen;
300 if (passlen != 24)
302 if (strequal(password, " "))
303 *password = 0;
304 passlen = strlen(password);
306 else if (doencrypt)
308 passlen = 0;
309 *password = 0;
312 p = strchr(path + 2, '\\');
313 if (!p)
314 return (ERROR(ERRSRV, ERRinvnetname));
315 fstrcpy(service, p + 1);
316 p = strchr(service, '%');
317 if (p)
319 *p++ = 0;
320 fstrcpy(user, p);
322 StrnCpy(devicename, path + strlen(path) + 1, 6);
323 DEBUG(4, ("Got device type %s\n", devicename));
326 * Ensure the user and password names are in UNIX codepage format.
329 dos_to_unix(user, True);
330 if (!doencrypt)
332 dos_to_unix(password, True);
335 map_nt_and_unix_username(global_myworkgroup, user, user, NULL);
337 conn = make_connection(service, user, global_myworkgroup, password,
338 passlen, devicename, vuid, &ecode);
340 if (!conn)
341 return (connection_error(inbuf, outbuf, ecode));
343 if (Protocol < PROTOCOL_NT1)
345 set_message(outbuf, 2, strlen(devicename) + 1, True);
346 pstrcpy(smb_buf(outbuf), devicename);
348 else
350 char *fsname = lp_fstype(SNUM(conn));
352 set_message(outbuf, 3, 3, True);
354 p = smb_buf(outbuf);
355 pstrcpy(p, devicename);
356 p = skip_string(p, 1); /* device name */
357 pstrcpy(p, fsname);
358 p = skip_string(p, 1); /* filesystem type e.g NTFS */
360 set_message(outbuf, 3, PTR_DIFF(p, smb_buf(outbuf)), False);
362 /* what does setting this bit do? It is set by NT4 and
363 may affect the ability to autorun mounted cdroms */
364 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
366 init_dfsroot(conn, inbuf, outbuf);
369 DEBUG(3, ("tconX service=%s user=%s\n", service, user));
371 /* set the incoming and outgoing tid to the just created one */
372 SSVAL(inbuf, smb_tid, conn->cnum);
373 SSVAL(outbuf, smb_tid, conn->cnum);
375 return chain_reply(inbuf, outbuf, length, bufsize);
379 /****************************************************************************
380 reply to an unknown type
381 ****************************************************************************/
382 int reply_unknown(char *inbuf, char *outbuf)
384 int type;
385 type = CVAL(inbuf, smb_com);
387 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
388 smb_fn_name(type), type, type));
390 return (ERROR(ERRSRV, ERRunknownsmb));
394 /****************************************************************************
395 reply to an ioctl
396 ****************************************************************************/
397 int reply_ioctl(connection_struct * conn,
398 char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
400 uint16 device = SVAL(inbuf, smb_vwv1);
401 uint16 function = SVAL(inbuf, smb_vwv2);
402 uint32 ioctl_code = (device << 16) + function;
403 int replysize, outsize;
404 char *p;
405 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
407 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
409 switch (ioctl_code)
411 case IOCTL_QUERY_JOB_INFO:
412 replysize = 32;
413 break;
414 default:
415 return (ERROR(ERRSRV, ERRnosupport));
418 outsize = set_message(outbuf, 8, replysize + 1, True);
419 SSVAL(outbuf, smb_vwv1, replysize); /* Total data bytes returned */
420 SSVAL(outbuf, smb_vwv5, replysize); /* Data bytes this buffer */
421 SSVAL(outbuf, smb_vwv6, 52); /* Offset to data */
422 p = smb_buf(outbuf) + 1; /* Allow for alignment */
424 switch (ioctl_code)
426 case IOCTL_QUERY_JOB_INFO:
427 SSVAL(p, 0, fsp->print_jobid); /* Job number */
428 StrnCpy(p + 2, global_myname, 15); /* Our NetBIOS name */
429 StrnCpy(p + 18, lp_servicename(SNUM(conn)), 13); /* Service name */
430 break;
433 return outsize;
436 /****************************************************************************
437 always return an error: it's just a matter of which one...
438 ****************************************************************************/
439 static int session_trust_account(connection_struct * conn,
440 char *inbuf, char *outbuf,
441 char *user, char *domain,
442 char *smb_passwd, int smb_passlen,
443 char *smb_nt_passwd, int smb_nt_passlen)
445 uchar last_chal[8];
446 uint32 status = 0x0;
448 if (lp_security() != SEC_USER)
450 DEBUG(0,
451 ("session_trust_account: Trust account %s only supported with security = user\n",
452 user));
453 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
454 return (ERROR(0, 0xc0000000 | NT_STATUS_LOGON_FAILURE));
457 if (last_challenge(last_chal))
459 NET_USER_INFO_3 info3;
460 ZERO_STRUCT(info3);
461 status = check_domain_security(user, domain,
462 last_chal,
463 (uchar *) smb_passwd,
464 smb_passlen,
465 (uchar *) smb_nt_passwd,
466 smb_nt_passlen, &info3);
468 else
470 status = 0xc0000000 | NT_STATUS_LOGON_FAILURE;
473 if (status == 0x0)
475 status = 0xc0000000 | NT_STATUS_LOGON_FAILURE;
478 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
479 return ERROR(0, status);
482 /****************************************************************************
483 Return a bad password error configured for the correct client type.
484 ****************************************************************************/
486 static int bad_password_error(char *inbuf, char *outbuf)
488 enum remote_arch_types ra_type = get_remote_arch();
490 if (((ra_type == RA_WINNT) || (ra_type == RA_WIN2K)) &&
491 (global_client_caps & (CAP_NT_SMBS | CAP_STATUS32)))
493 SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
494 return (ERROR(0, 0xc0000000 | NT_STATUS_LOGON_FAILURE));
497 return (ERROR(ERRSRV, ERRbadpw));
500 /****************************************************************************
501 reply to a session setup command
502 ****************************************************************************/
504 int reply_sesssetup_and_X(connection_struct * conn, char *inbuf, char *outbuf,
505 int length, int bufsize)
507 uint16 sess_vuid;
508 NET_USER_INFO_3 info3;
509 int gid;
510 int uid;
511 int smb_bufsize;
512 int smb_apasslen = 0;
513 pstring smb_apasswd;
514 int smb_ntpasslen = 0;
515 pstring smb_ntpasswd;
516 pstring user;
517 pstring orig_user;
518 BOOL guest = False;
519 static BOOL done_sesssetup = False;
520 BOOL doencrypt = SMBENCRYPT();
521 char *domain = "";
523 ZERO_STRUCT(info3);
525 *smb_apasswd = 0;
526 *smb_ntpasswd = 0;
528 smb_bufsize = SVAL(inbuf, smb_vwv2);
530 if (Protocol < PROTOCOL_NT1)
532 smb_apasslen = SVAL(inbuf, smb_vwv7);
533 if (smb_apasslen > MAX_PASS_LEN)
535 overflow_attack(smb_apasslen);
538 memcpy(smb_apasswd, smb_buf(inbuf), smb_apasslen);
539 smb_apasswd[smb_apasslen] = 0;
540 pstrcpy(user, smb_buf(inbuf) + smb_apasslen);
542 if (!doencrypt && (lp_security() != SEC_SERVER))
544 smb_apasslen = strlen(smb_apasswd);
547 if (lp_server_ntlmv2() == True)
549 DEBUG(1,
550 ("NTLMv2-only accepted with NT LANMAN 1.0 and above.\n\
551 user %s attempted down-level SMB connection\n",
552 user));
553 return (ERROR(ERRSRV, ERRbadpw));
556 else
558 uint16 passlen1 = SVAL(inbuf, smb_vwv7);
559 uint16 passlen2 = SVAL(inbuf, smb_vwv8);
560 enum remote_arch_types ra_type = get_remote_arch();
561 char *p = smb_buf(inbuf);
563 if (global_client_caps == 0)
564 global_client_caps = IVAL(inbuf, smb_vwv11);
566 /* client_caps is used as final determination if client is NT or Win95.
567 This is needed to return the correct error codes in some
568 circumstances.
571 if (ra_type == RA_WINNT || ra_type == RA_WIN2K
572 || ra_type == RA_WIN95)
574 if (!
575 (global_client_caps &
576 (CAP_NT_SMBS | CAP_STATUS32)))
578 set_remote_arch(RA_WIN95);
582 if (passlen1 != 24 && passlen2 <= 24)
583 doencrypt = False;
585 if (passlen1 > MAX_PASS_LEN)
587 overflow_attack(passlen1);
590 passlen1 = MIN(passlen1, MAX_PASS_LEN);
591 passlen2 = MIN(passlen2, MAX_PASS_LEN);
593 if (!doencrypt)
595 /* both Win95 and WinNT stuff up the password
596 * lengths for non-encrypting systems. Uggh.
597 * if passlen1==24 its a win95 system, and its
598 * setting the password length incorrectly. Luckily
599 * it still works with the default code because
600 * Win95 will null terminate the password anyway
601 * if passlen1>0 and passlen2>0 then maybe its a
602 * NT box and its setting passlen2 to some random
603 * value which really stuffs things up. we need to
604 * fix that one.
606 * LKCLXXXX: the random value can be random 16 bit.
607 * old test used to have ... && passlen <= 24)
608 * which of course fails most of the time.
611 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 1)
612 passlen2 = 0;
615 if (lp_restrict_anonymous())
617 /* there seems to be no reason behind the differences in MS clients formatting
618 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
619 * in particular seems to have an extra null byte between the username and the
620 * domain, or the password length calculation is wrong, which throws off the
621 * string extraction routines below. This makes the value of domain be the
622 * empty string, which fails the restrict anonymous check further down.
623 * This compensates for that, and allows browsing to work in mixed NT and
624 * win95 environments even when restrict anonymous is true. AAB
626 dump_data(100, p, 0x70);
627 DEBUG(9,
628 ("passlen1=%d, passlen2=%d\n", passlen1,
629 passlen2));
630 if (ra_type == RA_WIN95 && !passlen1 && !passlen2
631 && p[0] == 0 && p[1] == 0)
633 DEBUG(0,
634 ("restrict anonymous parameter used in a win95 environment!\n"));
635 DEBUG(0,
636 ("client is win95 and broken passlen1 offset -- attempting fix\n"));
637 DEBUG(0,
638 ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
639 passlen1 = 1;
643 if (doencrypt
644 || ((lp_security() == SEC_SERVER)
645 || (lp_security() == SEC_DOMAIN)))
647 /* Save the lanman2 password and the NT md4 password. */
648 smb_apasslen = passlen1;
649 memcpy(smb_apasswd, p, smb_apasslen);
650 smb_apasswd[smb_apasslen] = 0;
651 smb_ntpasslen = passlen2;
652 memcpy(smb_ntpasswd, p + passlen1, smb_ntpasslen);
653 smb_ntpasswd[smb_ntpasslen] = 0;
656 * Ensure the plaintext passwords are in UNIX format.
658 if (!doencrypt)
660 dos_to_unix(smb_apasswd, True);
661 dos_to_unix(smb_ntpasswd, True);
665 else
667 /* we use the first password that they gave */
668 smb_apasslen = passlen1;
669 StrnCpy(smb_apasswd, p, smb_apasslen);
671 * Ensure the plaintext password is in UNIX format.
673 dos_to_unix(smb_apasswd, True);
675 /* trim the password */
676 smb_apasslen = strlen(smb_apasswd);
678 /* wfwg sometimes uses a space instead of a null */
679 if (strequal(smb_apasswd, " "))
681 smb_apasslen = 0;
682 *smb_apasswd = 0;
686 if (passlen2 == 0 && smb_apasslen == 0 && ra_type == RA_WIN95)
688 /* work-around for win95 NULL sessions, where NULL password is
689 actually put in the data stream before the domain name etc */
690 p++;
692 else
694 p += passlen1 + passlen2;
697 fstrcpy(user, p);
698 p = skip_string(p, 1);
700 * Incoming user is in DOS codepage format. Convert
701 * to UNIX.
703 dos_to_unix(user, True);
704 domain = p;
706 DEBUG(3,
707 ("passlen: %d %d Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
708 passlen1, passlen2, domain, skip_string(p, 1),
709 skip_string(p, 2)));
712 DEBUG(3, ("sesssetupX:name=[%s]\n", user));
715 * If name ends in $ it's a trust account.
718 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24)
719 && (smb_ntpasslen == 24))
721 return session_trust_account(conn, inbuf, outbuf, user,
722 domain, smb_apasswd,
723 smb_apasslen, smb_ntpasswd,
724 smb_ntpasslen);
727 if (done_sesssetup && lp_restrict_anonymous())
729 /* tests show that even if browsing is done over
730 * already validated connections without a username
731 * and password the domain is still provided, which it
732 * wouldn't be if it was a purely anonymous connection.
733 * So, in order to restrict anonymous, we only deny
734 * connections that have no session information. If a
735 * domain has been provided, then it's not a purely
736 * anonymous connection. AAB
738 if (!*user && !*smb_apasswd && !*domain)
740 DEBUG(0,
741 ("restrict anonymous is True and anonymous "
742 "connection attempted. Denying access.\n"));
743 return (ERROR(ERRDOS, ERRnoaccess));
747 /* If no username is sent use the guest account */
748 if (!*user)
750 pstrcpy(user, lp_guestaccount(-1));
751 /* If no user and no password then set guest flag. */
752 if (*smb_apasswd == 0)
753 guest = True;
756 strlower(user);
759 * map from DOS codepage format to Unix
762 dos_to_unix(user, True);
765 * In share level security, only overwrite sesssetup_use if
766 * it's a non null-session share. Helps keep %U and %G
767 * working.
770 if ((lp_security() != SEC_SHARE) || (*user && !guest))
771 pstrcpy(sesssetup_user, user);
772 reload_services(True);
775 * Save the username before mapping. We will use
776 * the original username sent to us for security=server
777 * and security=domain checking.
780 pstrcpy(orig_user, user);
782 map_nt_and_unix_username(domain, user, user, NULL);
784 add_session_user(user);
787 * Check if the given username was the guest user with no password.
790 if (!guest && strequal(user, lp_guestaccount(-1))
791 && (*smb_apasswd == 0))
792 guest = True;
794 if (!guest && !check_hosts_equiv(user))
797 * Check with orig_user for security=server and
798 * security=domain.
801 DEBUG(10, ("Checking SMB password, user %s domain %s\n",
802 user, domain));
803 if (!password_ok(orig_user, domain,
804 smb_apasswd, smb_apasslen,
805 smb_ntpasswd, smb_ntpasslen, NULL, &info3))
807 DEBUG(0, ("SMB LM/NT Password did not match!\n"));
809 if (lp_security() >= SEC_USER)
811 if (lp_map_to_guest() == NEVER_MAP_TO_GUEST)
813 DEBUG(1,
814 ("Rejecting user '%s': authentication failed\n",
815 user));
816 return bad_password_error(inbuf,
817 outbuf);
820 if (lp_map_to_guest() ==
821 MAP_TO_GUEST_ON_BAD_USER)
823 if (Get_Pwnam(user, True))
825 DEBUG(1,
826 ("Rejecting user '%s': bad password\n",
827 user));
828 return
829 bad_password_error
830 (inbuf, outbuf);
835 * ..else if lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD
836 * Then always map to guest account - as done below.
840 if (*smb_apasswd || !Get_Pwnam(user, True))
841 pstrcpy(user, lp_guestaccount(-1));
842 DEBUG(3,
843 ("Registered username %s for guest access\n",
844 user));
845 guest = True;
850 if (!Get_Pwnam(user, True))
852 DEBUG(3, ("No such user %s - using guest account\n", user));
853 pstrcpy(user, lp_guestaccount(-1));
854 guest = True;
857 if (!strequal(user, lp_guestaccount(-1)) &&
858 lp_servicenumber(user) < 0)
860 int homes = lp_servicenumber(HOMES_NAME);
861 char *home = get_user_home_dir(user);
862 if (homes >= 0 && home)
864 pstring home_dir;
865 fstrcpy(home_dir, home);
866 lp_add_home(user, homes, home_dir);
871 /* it's ok - setup a reply */
872 if (Protocol < PROTOCOL_NT1)
874 set_message(outbuf, 3, 0, True);
876 else
878 char *p;
879 set_message(outbuf, 3, 3, True);
880 p = smb_buf(outbuf);
881 pstrcpy(p, "Unix");
882 p = skip_string(p, 1);
883 pstrcpy(p, "Samba ");
884 pstrcat(p, VERSION);
885 p = skip_string(p, 1);
886 pstrcpy(p, global_myworkgroup);
887 p = skip_string(p, 1);
888 set_message(outbuf, 3, PTR_DIFF(p, smb_buf(outbuf)), False);
889 /* perhaps grab OS version here?? */
892 /* Set the correct uid in the outgoing and incoming packets
893 We will use this on future requests to determine which
894 user we should become.
897 const struct passwd *pw = Get_Pwnam(user, False);
898 if (!pw)
900 DEBUG(1,
901 ("Username %s is invalid on this system\n",
902 user));
903 return bad_password_error(inbuf, outbuf);
905 gid = pw->pw_gid;
906 uid = pw->pw_uid;
909 if (guest)
910 SSVAL(outbuf, smb_vwv2, 1);
912 /* register the name and uid as being validated, so further connections
913 to a uid can get through without a password, on the same VC */
914 sess_vuid =
915 register_vuid(getpid(), uid, gid, user, sesssetup_user, guest,
916 &info3);
918 SSVAL(outbuf, smb_uid, sess_vuid);
919 SSVAL(inbuf, smb_uid, sess_vuid);
921 if (!done_sesssetup)
922 max_send = MIN(max_send, smb_bufsize);
924 DEBUG(6, ("Client requested max send size of %d\n", max_send));
926 done_sesssetup = True;
928 return chain_reply(inbuf, outbuf, length, bufsize);
932 /****************************************************************************
933 reply to a chkpth
934 ****************************************************************************/
935 int reply_chkpth(connection_struct * conn, char *inbuf, char *outbuf,
936 int dum_size, int dum_buffsize)
938 int outsize = 0;
939 int mode;
940 pstring name;
941 BOOL ok = False;
942 BOOL bad_path = False;
943 SMB_STRUCT_STAT st;
945 pstrcpy(name, smb_buf(inbuf) + 1);
947 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
949 unix_convert(name, conn, 0, &bad_path, &st);
951 mode = SVAL(inbuf, smb_vwv0);
953 if (check_name(name, conn))
955 if (VALID_STAT(st))
956 ok = S_ISDIR(st.st_mode);
957 else
958 ok = vfs_directory_exist(conn, name, NULL);
961 if (!ok)
963 /* We special case this - as when a Windows machine
964 is parsing a path is steps through the components
965 one at a time - if a component fails it expects
966 ERRbadpath, not ERRbadfile.
968 if (errno == ENOENT)
970 unix_ERR_class = ERRDOS;
971 unix_ERR_code = ERRbadpath;
974 #if 0
975 /* Ugly - NT specific hack - maybe not needed ? (JRA) */
976 if ((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
977 (get_remote_arch() == RA_WINNT))
979 unix_ERR_class = ERRDOS;
980 unix_ERR_code = ERRbaddirectory;
982 #endif
984 return (UNIXERROR(ERRDOS, ERRbadpath));
987 outsize = set_message(outbuf, 0, 0, True);
989 DEBUG(3, ("chkpth %s mode=%d\n", name, mode));
991 return (outsize);
995 /****************************************************************************
996 reply to a getatr
997 ****************************************************************************/
998 int reply_getatr(connection_struct * conn, char *inbuf, char *outbuf,
999 int dum_size, int dum_buffsize)
1001 pstring fname;
1002 int outsize = 0;
1003 SMB_STRUCT_STAT sbuf;
1004 BOOL ok = False;
1005 int mode = 0;
1006 SMB_OFF_T size = 0;
1007 time_t mtime = 0;
1008 BOOL bad_path = False;
1010 pstrcpy(fname, smb_buf(inbuf) + 1);
1012 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1014 /* if((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && dfs_redirect(fname,conn)) return(dfs_path_error(inbuf,outbuf));
1016 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1017 under WfWg - weird! */
1018 if (!(*fname))
1020 mode = aHIDDEN | aDIR;
1021 if (!CAN_WRITE(conn))
1022 mode |= aRONLY;
1023 size = 0;
1024 mtime = 0;
1025 ok = True;
1027 else
1029 unix_convert(fname, conn, 0, &bad_path, &sbuf);
1030 if (check_name(fname, conn))
1032 if (VALID_STAT(sbuf) || dos_stat(fname, &sbuf) == 0)
1034 mode = dos_mode(conn, fname, &sbuf);
1035 size = sbuf.st_size;
1036 mtime = sbuf.st_mtime;
1037 if (mode & aDIR)
1038 size = 0;
1039 ok = True;
1041 else
1042 DEBUG(3,
1043 ("stat of %s failed (%s)\n", fname,
1044 strerror(errno)));
1048 if (!ok)
1050 if ((errno == ENOENT) && bad_path)
1052 unix_ERR_class = ERRDOS;
1053 unix_ERR_code = ERRbadpath;
1056 return (UNIXERROR(ERRDOS, ERRbadfile));
1059 outsize = set_message(outbuf, 10, 0, True);
1061 SSVAL(outbuf, smb_vwv0, mode);
1062 if (lp_dos_filetime_resolution(SNUM(conn)))
1063 put_dos_date3(outbuf, smb_vwv1, mtime & ~1);
1064 else
1065 put_dos_date3(outbuf, smb_vwv1, mtime);
1066 SIVAL(outbuf, smb_vwv3, (uint32)size);
1068 if (Protocol >= PROTOCOL_NT1)
1070 char *p = strrchr(fname, '/');
1071 uint16 flg2 = SVAL(outbuf, smb_flg2);
1072 if (!p)
1073 p = fname;
1074 if (!is_8_3(fname, True))
1075 SSVAL(outbuf, smb_flg2, flg2 | 0x40); /* IS_LONG_NAME */
1078 DEBUG(3,
1079 ("getatr name=%s mode=%d size=%d\n", fname, mode,
1080 (uint32)size));
1082 return (outsize);
1086 /****************************************************************************
1087 reply to a setatr
1088 ****************************************************************************/
1089 int reply_setatr(connection_struct * conn, char *inbuf, char *outbuf,
1090 int dum_size, int dum_buffsize)
1092 pstring fname;
1093 int outsize = 0;
1094 BOOL ok = False;
1095 int mode;
1096 time_t mtime;
1097 SMB_STRUCT_STAT st;
1098 BOOL bad_path = False;
1100 pstrcpy(fname, smb_buf(inbuf) + 1);
1101 unix_convert(fname, conn, 0, &bad_path, &st);
1103 mode = SVAL(inbuf, smb_vwv0);
1104 mtime = make_unix_date3(inbuf + smb_vwv1);
1106 if (VALID_STAT_OF_DIR(st) || vfs_directory_exist(conn, fname, NULL))
1107 mode |= aDIR;
1108 if (check_name(fname, conn))
1109 ok = (file_chmod(conn, fname, mode, NULL) == 0);
1110 if (ok)
1111 ok = set_filetime(conn, fname, mtime);
1113 if (!ok)
1115 if ((errno == ENOENT) && bad_path)
1117 unix_ERR_class = ERRDOS;
1118 unix_ERR_code = ERRbadpath;
1121 return (UNIXERROR(ERRDOS, ERRnoaccess));
1124 outsize = set_message(outbuf, 0, 0, True);
1126 DEBUG(3, ("setatr name=%s mode=%d\n", fname, mode));
1128 return (outsize);
1132 /****************************************************************************
1133 reply to a dskattr
1134 ****************************************************************************/
1135 int reply_dskattr(connection_struct * conn, char *inbuf, char *outbuf,
1136 int dum_size, int dum_buffsize)
1138 int outsize = 0;
1139 SMB_BIG_UINT dfree, dsize, bsize;
1141 conn->vfs_ops.disk_free(".", True, &bsize, &dfree, &dsize);
1143 outsize = set_message(outbuf, 5, 0, True);
1145 SSVAL(outbuf, smb_vwv0, dsize);
1146 SSVAL(outbuf, smb_vwv1, bsize / 512);
1147 SSVAL(outbuf, smb_vwv2, 512);
1148 SSVAL(outbuf, smb_vwv3, dfree);
1150 DEBUG(3, ("dskattr dfree=%d\n", (unsigned int)dfree));
1152 return (outsize);
1156 /****************************************************************************
1157 reply to a search
1158 Can be called from SMBsearch, SMBffirst or SMBfunique.
1159 ****************************************************************************/
1160 int reply_search(connection_struct * conn, char *inbuf, char *outbuf,
1161 int dum_size, int dum_buffsize)
1163 pstring mask;
1164 pstring directory;
1165 pstring fname;
1166 SMB_OFF_T size;
1167 int mode;
1168 time_t date;
1169 int dirtype;
1170 int outsize = 0;
1171 int numentries = 0;
1172 BOOL finished = False;
1173 int maxentries;
1174 int i;
1175 char *p;
1176 BOOL ok = False;
1177 int status_len;
1178 char *path;
1179 char status[21];
1180 int dptr_num = -1;
1181 BOOL check_descend = False;
1182 BOOL expect_close = False;
1183 BOOL can_open = True;
1184 BOOL bad_path = False;
1186 *mask = *directory = *fname = 0;
1188 /* If we were called as SMBffirst then we must expect close. */
1189 if (CVAL(inbuf, smb_com) == SMBffirst)
1190 expect_close = True;
1192 outsize = set_message(outbuf, 1, 3, True);
1193 maxentries = SVAL(inbuf, smb_vwv0);
1194 dirtype = SVAL(inbuf, smb_vwv1);
1195 path = smb_buf(inbuf) + 1;
1196 status_len = SVAL(smb_buf(inbuf), 3 + strlen(path));
1199 /* dirtype &= ~aDIR; */
1201 DEBUG(5, ("reply_search: path=%s status_len=%d\n", path, status_len));
1204 if (status_len == 0)
1206 pstring dir2;
1208 pstrcpy(directory, smb_buf(inbuf) + 1);
1209 pstrcpy(dir2, smb_buf(inbuf) + 1);
1210 unix_convert(directory, conn, 0, &bad_path, NULL);
1211 unix_format(dir2);
1213 if (!check_name(directory, conn))
1214 can_open = False;
1216 p = strrchr(dir2, '/');
1217 if (p == NULL)
1219 pstrcpy(mask, dir2);
1220 *dir2 = 0;
1222 else
1224 *p = 0;
1225 pstrcpy(mask, p + 1);
1228 p = strrchr(directory, '/');
1229 if (!p)
1230 *directory = 0;
1231 else
1232 *p = 0;
1234 if (strlen(directory) == 0)
1235 pstrcpy(directory, "./");
1236 memset((char *)status, '\0', 21);
1237 CVAL(status, 0) = dirtype;
1239 else
1241 memcpy(status, smb_buf(inbuf) + 1 + strlen(path) + 4, 21);
1242 memcpy(mask, status + 1, 11);
1243 mask[11] = 0;
1244 dirtype = CVAL(status, 0) & 0x1F;
1245 conn->dirptr = dptr_fetch(status + 12, &dptr_num);
1246 if (!conn->dirptr)
1247 goto SearchEmpty;
1248 string_set(&conn->dirpath, dptr_path(dptr_num));
1249 if (!case_sensitive)
1250 strnorm(mask);
1253 /* turn strings of spaces into a . */
1255 trim_string(mask, NULL, " ");
1256 if ((p = strrchr(mask, ' ')))
1258 fstring ext;
1259 fstrcpy(ext, p + 1);
1260 *p = 0;
1261 trim_string(mask, NULL, " ");
1262 pstrcat(mask, ".");
1263 pstrcat(mask, ext);
1267 /* Convert the formatted mask. (This code lives in trans2.c) */
1268 mask_convert(mask);
1271 int skip;
1272 p = mask;
1273 while (*p)
1275 if ((skip = get_character_len(*p)) != 0)
1277 p += skip;
1279 else
1281 if (*p != '?' && *p != '*' && !isdoschar(*p))
1283 DEBUG(5,
1284 ("Invalid char [%c] in search mask?\n",
1285 *p));
1286 *p = '?';
1288 p++;
1293 if (!strchr(mask, '.') && strlen(mask) > 8)
1295 fstring tmp;
1296 fstrcpy(tmp, &mask[8]);
1297 mask[8] = '.';
1298 mask[9] = 0;
1299 pstrcat(mask, tmp);
1302 DEBUG(5, ("mask=%s directory=%s\n", mask, directory));
1304 if (can_open)
1306 p = smb_buf(outbuf) + 3;
1308 ok = True;
1310 if (status_len == 0)
1312 dptr_num =
1313 dptr_create(conn, directory, True,
1314 expect_close, SVAL(inbuf,
1315 smb_pid));
1316 if (dptr_num < 0)
1318 if (dptr_num == -2)
1320 if ((errno == ENOENT) && bad_path)
1322 unix_ERR_class = ERRDOS;
1323 unix_ERR_code = ERRbadpath;
1325 return (UNIXERROR(ERRDOS, ERRnofids));
1327 return (ERROR(ERRDOS, ERRnofids));
1331 DEBUG(4, ("dptr_num is %d\n", dptr_num));
1333 if (ok)
1335 if ((dirtype & 0x1F) == aVOLID)
1337 memcpy(p, status, 21);
1338 make_dir_struct(p, "???????????",
1339 volume_label(SNUM(conn)), 0,
1340 aVOLID, 0);
1341 dptr_fill(p + 12, dptr_num);
1342 if (dptr_zero(p + 12) && (status_len == 0))
1343 numentries = 1;
1344 else
1345 numentries = 0;
1346 p += DIR_STRUCT_SIZE;
1348 else
1350 DEBUG(8, ("dirpath=<%s> dontdescend=<%s>\n",
1351 conn->dirpath,
1352 lp_dontdescend(SNUM(conn))));
1353 if (in_list
1354 (conn->dirpath,
1355 lp_dontdescend(SNUM(conn)), True))
1356 check_descend = True;
1358 for (i = numentries;
1359 (i < maxentries) && !finished; i++)
1361 finished =
1362 !get_dir_entry(conn, mask,
1363 dirtype, fname,
1364 &size, &mode,
1365 &date,
1366 check_descend);
1367 if (!finished)
1369 memcpy(p, status, 21);
1370 make_dir_struct(p, mask,
1371 fname, size,
1372 mode, date);
1373 dptr_fill(p + 12, dptr_num);
1374 numentries++;
1376 p += DIR_STRUCT_SIZE;
1379 } /* if (ok ) */
1383 SearchEmpty:
1385 if (numentries == 0 || !ok)
1387 CVAL(outbuf, smb_rcls) = ERRDOS;
1388 SSVAL(outbuf, smb_err, ERRnofiles);
1389 dptr_close(&dptr_num);
1392 /* If we were called as SMBffirst with smb_search_id == NULL
1393 and no entries were found then return error and close dirptr
1394 (X/Open spec) */
1396 if (ok && expect_close && numentries == 0 && status_len == 0)
1398 CVAL(outbuf, smb_rcls) = ERRDOS;
1399 SSVAL(outbuf, smb_err, ERRnofiles);
1400 /* Also close the dptr - we know it's gone */
1401 dptr_close(&dptr_num);
1404 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1405 if (dptr_num >= 0 && CVAL(inbuf, smb_com) == SMBfunique)
1406 dptr_close(&dptr_num);
1408 SSVAL(outbuf, smb_vwv0, numentries);
1409 SSVAL(outbuf, smb_vwv1, 3 + numentries * DIR_STRUCT_SIZE);
1410 CVAL(smb_buf(outbuf), 0) = 5;
1411 SSVAL(smb_buf(outbuf), 1, numentries * DIR_STRUCT_SIZE);
1413 if (Protocol >= PROTOCOL_NT1)
1415 uint16 flg2 = SVAL(outbuf, smb_flg2);
1416 SSVAL(outbuf, smb_flg2, flg2 | 0x40); /* IS_LONG_NAME */
1419 outsize += DIR_STRUCT_SIZE * numentries;
1420 smb_setlen(outbuf, outsize - 4);
1422 if ((!*directory) && dptr_path(dptr_num))
1423 slprintf(directory, sizeof(directory) - 1, "(%s)",
1424 dptr_path(dptr_num));
1426 DEBUG(4, ("%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1427 smb_fn_name(CVAL(inbuf, smb_com)),
1428 mask, directory, dirtype, numentries, maxentries));
1430 return (outsize);
1434 /****************************************************************************
1435 reply to a fclose (stop directory search)
1436 ****************************************************************************/
1437 int reply_fclose(connection_struct * conn, char *inbuf, char *outbuf,
1438 int dum_size, int dum_buffsize)
1440 int outsize = 0;
1441 int status_len;
1442 char *path;
1443 char status[21];
1444 int dptr_num = -2;
1446 outsize = set_message(outbuf, 1, 0, True);
1447 path = smb_buf(inbuf) + 1;
1448 status_len = SVAL(smb_buf(inbuf), 3 + strlen(path));
1451 if (status_len == 0)
1452 return (ERROR(ERRSRV, ERRsrverror));
1454 memcpy(status, smb_buf(inbuf) + 1 + strlen(path) + 4, 21);
1456 if (dptr_fetch(status + 12, &dptr_num))
1458 /* Close the dptr - we know it's gone */
1459 dptr_close(&dptr_num);
1462 SSVAL(outbuf, smb_vwv0, 0);
1464 DEBUG(3, ("search close\n"));
1466 return (outsize);
1470 /****************************************************************************
1471 reply to an open
1472 ****************************************************************************/
1474 int reply_open(connection_struct * conn, char *inbuf, char *outbuf,
1475 int dum_size, int dum_buffsize)
1477 pstring fname;
1478 int outsize = 0;
1479 int fmode = 0;
1480 int share_mode;
1481 SMB_OFF_T size = 0;
1482 time_t mtime = 0;
1483 mode_t unixmode;
1484 int rmode = 0;
1485 SMB_STRUCT_STAT sbuf;
1486 BOOL bad_path = False;
1487 files_struct *fsp;
1488 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1490 share_mode = SVAL(inbuf, smb_vwv0);
1492 pstrcpy(fname, smb_buf(inbuf) + 1);
1494 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1496 unix_convert(fname, conn, 0, &bad_path, NULL);
1498 unixmode = unix_mode(conn, aARCH, fname);
1500 fsp =
1501 open_file_shared(conn, fname, share_mode,
1502 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN),
1503 unixmode, oplock_request, &rmode, NULL);
1505 if (!fsp)
1507 if ((errno == ENOENT) && bad_path)
1509 unix_ERR_class = ERRDOS;
1510 unix_ERR_code = ERRbadpath;
1512 return (UNIXERROR(ERRDOS, ERRnoaccess));
1515 if (fsp->conn->vfs_ops.fstat(fsp->fd, &sbuf) != 0)
1517 close_file(fsp, False);
1518 return (ERROR(ERRDOS, ERRnoaccess));
1521 size = sbuf.st_size;
1522 fmode = dos_mode(conn, fname, &sbuf);
1523 mtime = sbuf.st_mtime;
1525 if (fmode & aDIR)
1527 DEBUG(3, ("attempt to open a directory %s\n", fname));
1528 close_file(fsp, False);
1529 return (ERROR(ERRDOS, ERRnoaccess));
1532 outsize = set_message(outbuf, 7, 0, True);
1533 SSVAL(outbuf, smb_vwv0, fsp->fnum);
1534 SSVAL(outbuf, smb_vwv1, fmode);
1535 if (lp_dos_filetime_resolution(SNUM(conn)))
1536 put_dos_date3(outbuf, smb_vwv2, mtime & ~1);
1537 else
1538 put_dos_date3(outbuf, smb_vwv2, mtime);
1539 SIVAL(outbuf, smb_vwv4, (uint32)size);
1540 SSVAL(outbuf, smb_vwv6, rmode);
1542 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1544 CVAL(outbuf, smb_flg) |= CORE_OPLOCK_GRANTED;
1547 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1548 CVAL(outbuf, smb_flg) |= CORE_OPLOCK_GRANTED;
1549 return (outsize);
1553 /****************************************************************************
1554 reply to an open and X
1555 ****************************************************************************/
1556 int reply_open_and_X(connection_struct * conn, char *inbuf, char *outbuf,
1557 int length, int bufsize)
1559 pstring fname;
1560 int smb_mode = SVAL(inbuf, smb_vwv3);
1561 int smb_attr = SVAL(inbuf, smb_vwv5);
1562 /* Breakout the oplock request bits so we can set the
1563 reply bits separately. */
1564 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1565 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1566 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1567 #if 0
1568 int open_flags = SVAL(inbuf, smb_vwv2);
1569 int smb_sattr = SVAL(inbuf, smb_vwv4);
1570 uint32 smb_time = make_unix_date3(inbuf + smb_vwv6);
1571 #endif
1572 int smb_ofun = SVAL(inbuf, smb_vwv8);
1573 mode_t unixmode;
1574 SMB_OFF_T size = 0;
1575 int fmode = 0, mtime = 0, rmode = 0;
1576 SMB_STRUCT_STAT sbuf;
1577 int smb_action = 0;
1578 BOOL bad_path = False;
1579 files_struct *fsp;
1581 /* If it's an IPC, pass off the pipe handler. */
1582 if (IS_IPC(conn) && lp_nt_pipe_support())
1583 return reply_open_pipe_and_X(conn, inbuf, outbuf, length,
1584 bufsize);
1586 /* XXXX we need to handle passed times, sattr and flags */
1588 pstrcpy(fname, smb_buf(inbuf));
1590 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1592 unix_convert(fname, conn, 0, &bad_path, NULL);
1594 unixmode = unix_mode(conn, smb_attr | aARCH, fname);
1596 fsp = open_file_shared(conn, fname, smb_mode, smb_ofun, unixmode,
1597 oplock_request, &rmode, &smb_action);
1599 if (!fsp)
1601 if ((errno == ENOENT) && bad_path)
1603 unix_ERR_class = ERRDOS;
1604 unix_ERR_code = ERRbadpath;
1606 return (UNIXERROR(ERRDOS, ERRnoaccess));
1609 if (fsp->conn->vfs_ops.fstat(fsp->fd, &sbuf) != 0)
1611 close_file(fsp, False);
1612 return (ERROR(ERRDOS, ERRnoaccess));
1615 size = sbuf.st_size;
1616 fmode = dos_mode(conn, fname, &sbuf);
1617 mtime = sbuf.st_mtime;
1618 if (fmode & aDIR)
1620 close_file(fsp, False);
1621 return (ERROR(ERRDOS, ERRnoaccess));
1624 /* If the caller set the extended oplock request bit
1625 and we granted one (by whatever means) - set the
1626 correct bit for extended oplock reply.
1629 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1631 smb_action |= EXTENDED_OPLOCK_GRANTED;
1634 if (ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1636 smb_action |= EXTENDED_OPLOCK_GRANTED;
1639 /* If the caller set the core oplock request bit
1640 and we granted one (by whatever means) - set the
1641 correct bit for core oplock reply.
1644 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1646 CVAL(outbuf, smb_flg) |= CORE_OPLOCK_GRANTED;
1649 if (core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1651 CVAL(outbuf, smb_flg) |= CORE_OPLOCK_GRANTED;
1654 set_message(outbuf, 15, 0, True);
1655 SSVAL(outbuf, smb_vwv2, fsp->fnum);
1656 SSVAL(outbuf, smb_vwv3, fmode);
1657 if (lp_dos_filetime_resolution(SNUM(conn)))
1658 put_dos_date3(outbuf, smb_vwv4, mtime & ~1);
1659 else
1660 put_dos_date3(outbuf, smb_vwv4, mtime);
1661 SIVAL(outbuf, smb_vwv6, (uint32)size);
1662 SSVAL(outbuf, smb_vwv8, rmode);
1663 SSVAL(outbuf, smb_vwv11, smb_action);
1665 return chain_reply(inbuf, outbuf, length, bufsize);
1669 /****************************************************************************
1670 reply to a SMBulogoffX
1671 ****************************************************************************/
1672 int reply_ulogoffX(connection_struct * conn, char *inbuf, char *outbuf,
1673 int length, int bufsize)
1675 uint16 vuid = SVAL(inbuf, smb_uid);
1676 vuser_key key;
1677 user_struct *vuser = NULL;
1678 key.pid = conn != NULL ? conn->smbd_pid : getpid();
1679 key.vuid = vuid;
1680 vuser = get_valid_user_struct(&key);
1682 if (vuser == 0)
1684 DEBUG(3,
1685 ("ulogoff, vuser id %d does not map to user.\n", vuid));
1688 /* in user level security we are supposed to close any files
1689 open by this user */
1690 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1692 file_close_user(vuid);
1695 invalidate_vuid(&key);
1697 set_message(outbuf, 2, 0, True);
1699 DEBUG(3, ("ulogoffX vuid=%d\n", vuid));
1701 return chain_reply(inbuf, outbuf, length, bufsize);
1705 /****************************************************************************
1706 reply to a mknew or a create
1707 ****************************************************************************/
1708 int reply_mknew(connection_struct * conn, char *inbuf, char *outbuf,
1709 int dum_size, int dum_buffsize)
1711 pstring fname;
1712 int com;
1713 int outsize = 0;
1714 int createmode;
1715 mode_t unixmode;
1716 int ofun = 0;
1717 BOOL bad_path = False;
1718 files_struct *fsp;
1719 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1721 com = SVAL(inbuf, smb_com);
1723 createmode = SVAL(inbuf, smb_vwv0);
1724 pstrcpy(fname, smb_buf(inbuf) + 1);
1726 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1728 unix_convert(fname, conn, 0, &bad_path, NULL);
1730 if (createmode & aVOLID)
1732 DEBUG(0,
1733 ("Attempt to create file (%s) with volid set - please report this\n",
1734 fname));
1737 unixmode = unix_mode(conn, createmode, fname);
1739 if (com == SMBmknew)
1741 /* We should fail if file exists. */
1742 ofun = FILE_CREATE_IF_NOT_EXIST;
1744 else
1746 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1747 ofun = FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_TRUNCATE;
1750 /* Open file in dos compatibility share mode. */
1751 fsp =
1752 open_file_shared(conn, fname,
1753 SET_DENY_MODE(DENY_FCB) |
1754 SET_OPEN_MODE(DOS_OPEN_FCB), ofun, unixmode,
1755 oplock_request, NULL, NULL);
1757 if (!fsp)
1759 if ((errno == ENOENT) && bad_path)
1761 unix_ERR_class = ERRDOS;
1762 unix_ERR_code = ERRbadpath;
1764 return (UNIXERROR(ERRDOS, ERRnoaccess));
1767 outsize = set_message(outbuf, 1, 0, True);
1768 SSVAL(outbuf, smb_vwv0, fsp->fnum);
1770 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1772 CVAL(outbuf, smb_flg) |= CORE_OPLOCK_GRANTED;
1775 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1776 CVAL(outbuf, smb_flg) |= CORE_OPLOCK_GRANTED;
1778 DEBUG(2, ("new file %s\n", fname));
1779 DEBUG(3, ("mknew %s fd=%d dmode=%d umode=%o\n",
1780 fname, fsp->fd, createmode, (int)unixmode));
1782 return (outsize);
1786 /****************************************************************************
1787 reply to a create temporary file
1788 ****************************************************************************/
1789 int reply_ctemp(connection_struct * conn, char *inbuf, char *outbuf,
1790 int dum_size, int dum_buffsize)
1792 pstring fname;
1793 pstring fname2;
1794 int outsize = 0;
1795 int createmode;
1796 mode_t unixmode;
1797 BOOL bad_path = False;
1798 files_struct *fsp;
1799 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1801 createmode = SVAL(inbuf, smb_vwv0);
1802 pstrcpy(fname, smb_buf(inbuf) + 1);
1803 pstrcat(fname, "/TMXXXXXX");
1805 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1807 unix_convert(fname, conn, 0, &bad_path, NULL);
1809 unixmode = unix_mode(conn, createmode, fname);
1811 pstrcpy(fname2, (char *)smbd_mktemp(fname));
1813 /* Open file in dos compatibility share mode. */
1814 /* We should fail if file exists. */
1815 fsp =
1816 open_file_shared(conn, fname2,
1817 SET_DENY_MODE(DENY_FCB) |
1818 SET_OPEN_MODE(DOS_OPEN_FCB),
1819 (FILE_CREATE_IF_NOT_EXIST |
1820 FILE_EXISTS_FAIL), unixmode, oplock_request,
1821 NULL, NULL);
1823 if (!fsp)
1825 if ((errno == ENOENT) && bad_path)
1827 unix_ERR_class = ERRDOS;
1828 unix_ERR_code = ERRbadpath;
1830 return (UNIXERROR(ERRDOS, ERRnoaccess));
1833 outsize = set_message(outbuf, 1, 2 + strlen(fname2), True);
1834 SSVAL(outbuf, smb_vwv0, fsp->fnum);
1835 CVAL(smb_buf(outbuf), 0) = 4;
1836 pstrcpy(smb_buf(outbuf) + 1, fname2);
1838 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1840 CVAL(outbuf, smb_flg) |= CORE_OPLOCK_GRANTED;
1843 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1844 CVAL(outbuf, smb_flg) |= CORE_OPLOCK_GRANTED;
1846 DEBUG(2, ("created temp file %s\n", fname2));
1847 DEBUG(3, ("ctemp %s fd=%d dmode=%d umode=%o\n",
1848 fname2, fsp->fd, createmode, (int)unixmode));
1850 return (outsize);
1854 /*******************************************************************
1855 check if a user is allowed to delete a file
1856 ********************************************************************/
1857 static BOOL can_delete(char *fname, connection_struct * conn, int dirtype)
1859 SMB_STRUCT_STAT sbuf;
1860 int fmode;
1862 if (!CAN_WRITE(conn))
1863 return (False);
1865 if (conn->vfs_ops.lstat(dos_to_unix(fname, False), &sbuf) != 0)
1866 return (False);
1867 fmode = dos_mode(conn, fname, &sbuf);
1868 if (fmode & aDIR)
1869 return (False);
1870 if (!lp_delete_readonly(SNUM(conn)))
1872 if (fmode & aRONLY)
1873 return (False);
1875 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1876 return (False);
1877 if (!check_file_sharing(conn, fname, False))
1878 return (False);
1879 return (True);
1882 /****************************************************************************
1883 Reply to a unlink
1884 ****************************************************************************/
1885 int reply_unlink(connection_struct * conn, char *inbuf, char *outbuf,
1886 int dum_size, int dum_buffsize)
1888 int outsize = 0;
1889 pstring name;
1890 int dirtype;
1891 pstring directory;
1892 pstring mask;
1893 char *p;
1894 int count = 0;
1895 int error = ERRnoaccess;
1896 BOOL has_wild;
1897 BOOL exists = False;
1898 BOOL bad_path = False;
1899 BOOL rc = True;
1901 *directory = *mask = 0;
1903 dirtype = SVAL(inbuf, smb_vwv0);
1905 pstrcpy(name, smb_buf(inbuf) + 1);
1907 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1909 DEBUG(3, ("reply_unlink : %s\n", name));
1911 rc = unix_convert(name, conn, 0, &bad_path, NULL);
1913 p = strrchr(name, '/');
1914 if (!p)
1916 pstrcpy(directory, "./");
1917 pstrcpy(mask, name);
1919 else
1921 *p = 0;
1922 pstrcpy(directory, name);
1923 pstrcpy(mask, p + 1);
1927 * We should only check the mangled cache
1928 * here if unix_convert failed. This means
1929 * that the path in 'mask' doesn't exist
1930 * on the file system and so we need to look
1931 * for a possible mangle. This patch from
1932 * Tine Smukavec <valentin.smukavec@hermes.si>.
1935 if (!rc && is_mangled(mask))
1936 check_mangled_cache(mask);
1938 has_wild = strchr(mask, '*') || strchr(mask, '?');
1940 if (!has_wild)
1942 pstrcat(directory, "/");
1943 pstrcat(directory, mask);
1944 if (can_delete(directory, conn, dirtype)
1945 && !dos_unlink(directory))
1946 count++;
1947 if (!count)
1948 exists = vfs_file_exist(conn, directory, NULL);
1950 else
1952 void *dirptr = NULL;
1953 char *dname;
1955 if (check_name(directory, conn))
1956 dirptr = OpenDir(conn, directory, True);
1958 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1959 the pattern matches against the long name, otherwise the short name
1960 We don't implement this yet XXXX
1963 if (dirptr)
1965 error = ERRbadfile;
1967 if (strequal(mask, "????????.???"))
1968 pstrcpy(mask, "*");
1970 while ((dname = ReadDirName(dirptr)))
1972 pstring fname;
1973 pstrcpy(fname, dname);
1975 if (!mask_match
1976 (fname, mask, case_sensitive,
1977 False)) continue;
1979 error = ERRnoaccess;
1980 slprintf(fname, sizeof(fname) - 1, "%s/%s",
1981 directory, dname);
1982 if (!can_delete(fname, conn, dirtype))
1983 continue;
1984 if (!conn->vfs_ops.
1985 unlink(dos_to_unix(fname, False)))
1986 count++;
1987 DEBUG(3,
1988 ("reply_unlink : doing unlink on %s\n",
1989 fname));
1991 CloseDir(dirptr);
1995 if (count == 0)
1997 if (exists)
1998 return (ERROR(ERRDOS, error));
1999 else
2001 if ((errno == ENOENT) && bad_path)
2003 unix_ERR_class = ERRDOS;
2004 unix_ERR_code = ERRbadpath;
2006 return (UNIXERROR(ERRDOS, error));
2010 outsize = set_message(outbuf, 0, 0, True);
2012 return (outsize);
2016 /****************************************************************************
2017 reply to a readbraw (core+ protocol)
2018 ****************************************************************************/
2020 int reply_readbraw(connection_struct * conn, char *inbuf, char *outbuf,
2021 int dum_size, int dum_buffsize)
2023 size_t maxcount, mincount;
2024 size_t nread = 0;
2025 SMB_OFF_T startpos;
2026 char *header = outbuf;
2027 ssize_t ret = 0;
2028 files_struct *fsp;
2031 * Special check if an oplock break has been issued
2032 * and the readraw request croses on the wire, we must
2033 * return a zero length response here.
2036 if (global_oplock_break)
2038 _smb_setlen(header, 0);
2039 transfer_file(0, smbd_server_fd(), (SMB_OFF_T) 0, header, 4,
2041 DEBUG(5, ("readbraw - oplock break finished\n"));
2042 return -1;
2045 fsp = file_fsp(inbuf, smb_vwv0);
2047 if (!FNUM_OK(fsp, conn) || !fsp->can_read)
2050 * fsp could be NULL here so use the value from the packet. JRA.
2052 DEBUG(3,
2053 ("fnum %d not open in readbraw - cache prime?\n",
2054 (int)SVAL(inbuf, smb_vwv0)));
2055 _smb_setlen(header, 0);
2056 transfer_file(0, smbd_server_fd(), (SMB_OFF_T) 0, header, 4,
2058 return (-1);
2061 CHECK_FSP(fsp, conn);
2063 flush_write_cache(fsp, READRAW_FLUSH);
2065 startpos = IVAL(inbuf, smb_vwv1);
2066 if (CVAL(inbuf, smb_wct) == 10)
2069 * This is a large offset (64 bit) read.
2071 #ifdef LARGE_SMB_OFF_T
2073 startpos |= (((SMB_OFF_T) IVAL(inbuf, smb_vwv8)) << 32);
2075 #else /* !LARGE_SMB_OFF_T */
2078 * Ensure we haven't been sent a >32 bit offset.
2081 if (IVAL(inbuf, smb_vwv8) != 0)
2083 DEBUG(0,
2084 ("readbraw - large offset (%x << 32) used and we don't support \
2085 64 bit offsets.\n",
2086 (unsigned int)IVAL(inbuf, smb_vwv8)));
2087 _smb_setlen(header, 0);
2088 transfer_file(0, smbd_server_fd(), (SMB_OFF_T) 0,
2089 header, 4, 0);
2090 return (-1);
2093 #endif /* LARGE_SMB_OFF_T */
2095 if (startpos < 0)
2097 DEBUG(0,
2098 ("readbraw - negative 64 bit readraw offset (%.0f) !\n",
2099 (double)startpos));
2100 _smb_setlen(header, 0);
2101 transfer_file(0, smbd_server_fd(), (SMB_OFF_T) 0,
2102 header, 4, 0);
2103 return (-1);
2106 maxcount = (SVAL(inbuf, smb_vwv3) & 0xFFFF);
2107 mincount = (SVAL(inbuf, smb_vwv4) & 0xFFFF);
2109 /* ensure we don't overrun the packet size */
2110 maxcount = MIN(65535, maxcount);
2111 maxcount = MAX(mincount, maxcount);
2113 if (!is_locked
2114 (fsp, conn, (SMB_BIG_UINT) maxcount, (SMB_BIG_UINT) startpos,
2115 READ_LOCK))
2117 SMB_OFF_T size = fsp->size;
2118 SMB_OFF_T sizeneeded = startpos + maxcount;
2120 if (size < sizeneeded)
2122 SMB_STRUCT_STAT st;
2123 if (fsp->conn->vfs_ops.fstat(fsp->fd, &st) == 0)
2124 size = st.st_size;
2125 if (!fsp->can_write)
2126 fsp->size = size;
2129 nread = MIN(maxcount, (size - startpos));
2132 if (nread < mincount)
2133 nread = 0;
2135 DEBUG(3, ("readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n",
2136 fsp->fnum, (double)startpos,
2137 (int)maxcount, (int)mincount, (int)nread));
2139 #if UNSAFE_READRAW
2141 BOOL seek_fail = False;
2142 int predict = 0;
2143 _smb_setlen(header, nread);
2145 #if USE_READ_PREDICTION
2146 if (!fsp->can_write)
2147 predict =
2148 read_predict(fsp, fsp->fd, startpos,
2149 header + 4, NULL, nread);
2150 #endif /* USE_READ_PREDICTION */
2152 if ((nread - predict) > 0)
2154 if (conn->vfs_ops.seek(fsp, startpos + predict) == -1)
2156 DEBUG(0,
2157 ("reply_readbraw: ERROR: seek_file failed.\n"));
2158 ret = 0;
2159 seek_fail = True;
2163 if (!seek_fail)
2164 ret =
2165 (ssize_t) vfs_transfer_file(-1, fsp->fd,
2166 Client, NULL,
2167 (SMB_OFF_T) (nread
2169 predict),
2170 header,
2171 4 + predict,
2172 startpos +
2173 predict);
2176 if (ret != nread + 4)
2177 DEBUG(0,
2178 ("ERROR: file read failure on %s at %d for %d bytes (%d)\n",
2179 fsp->fsp_name, startpos, nread, ret));
2181 #else /* UNSAFE_READRAW */
2182 ret = read_file(fsp, header + 4, startpos, nread);
2183 if (ret < mincount)
2184 ret = 0;
2186 _smb_setlen(header, ret);
2187 transfer_file(0, smbd_server_fd(), 0, header, 4 + ret, 0);
2188 #endif /* UNSAFE_READRAW */
2190 DEBUG(5, ("readbraw finished\n"));
2191 return -1;
2195 /****************************************************************************
2196 reply to a lockread (core+ protocol)
2197 ****************************************************************************/
2198 int reply_lockread(connection_struct * conn, char *inbuf, char *outbuf,
2199 int length, int dum_buffsiz)
2201 ssize_t nread = -1;
2202 char *data;
2203 int outsize = 0;
2204 SMB_OFF_T startpos;
2205 size_t numtoread;
2206 int eclass;
2207 uint32 ecode;
2208 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
2210 CHECK_FSP(fsp, conn);
2211 CHECK_READ(fsp);
2212 CHECK_ERROR(fsp);
2214 numtoread = SVAL(inbuf, smb_vwv1);
2215 startpos = IVAL(inbuf, smb_vwv2);
2217 outsize = set_message(outbuf, 5, 3, True);
2218 numtoread = MIN(BUFFER_SIZE - outsize, numtoread);
2219 data = smb_buf(outbuf) + 3;
2222 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2223 * protocol request that predates the read/write lock concept.
2224 * Thus instead of asking for a read lock here we need to ask
2225 * for a write lock. JRA.
2228 if (!do_lock
2229 (fsp, conn, (SMB_BIG_UINT) numtoread, (SMB_BIG_UINT) startpos,
2230 WRITE_LOCK, &eclass, &ecode))
2232 if ((ecode == ERRlock) && lp_blocking_locks(SNUM(conn)))
2235 * A blocking lock was requested. Package up
2236 * this smb into a queued request and push it
2237 * onto the blocking lock queue.
2239 if (push_blocking_lock_request(inbuf, length, -1, 0))
2240 return -1;
2242 return (ERROR(eclass, ecode));
2245 nread = read_file(fsp, data, startpos, numtoread);
2247 if (nread < 0)
2248 return (UNIXERROR(ERRDOS, ERRnoaccess));
2250 outsize += nread;
2251 SSVAL(outbuf, smb_vwv0, nread);
2252 SSVAL(outbuf, smb_vwv5, nread + 3);
2253 SSVAL(smb_buf(outbuf), 1, nread);
2255 DEBUG(3, ("lockread fnum=%d num=%d nread=%d\n",
2256 fsp->fnum, (int)numtoread, (int)nread));
2258 return (outsize);
2262 /****************************************************************************
2263 reply to a read
2264 ****************************************************************************/
2266 int reply_read(connection_struct * conn, char *inbuf, char *outbuf, int size,
2267 int dum_buffsize)
2269 size_t numtoread;
2270 ssize_t nread = 0;
2271 char *data;
2272 SMB_OFF_T startpos;
2273 int outsize = 0;
2274 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
2276 CHECK_FSP(fsp, conn);
2277 CHECK_READ(fsp);
2278 CHECK_ERROR(fsp);
2280 numtoread = SVAL(inbuf, smb_vwv1);
2281 startpos = IVAL(inbuf, smb_vwv2);
2283 outsize = set_message(outbuf, 5, 3, True);
2284 numtoread = MIN(BUFFER_SIZE - outsize, numtoread);
2285 data = smb_buf(outbuf) + 3;
2287 if (is_locked
2288 (fsp, conn, (SMB_BIG_UINT) numtoread, (SMB_BIG_UINT) startpos,
2289 READ_LOCK))
2290 return (ERROR(ERRDOS, ERRlock));
2292 if (numtoread > 0)
2293 nread = read_file(fsp, data, startpos, numtoread);
2295 if (nread < 0)
2296 return (UNIXERROR(ERRDOS, ERRnoaccess));
2298 outsize += nread;
2299 SSVAL(outbuf, smb_vwv0, nread);
2300 SSVAL(outbuf, smb_vwv5, nread + 3);
2301 CVAL(smb_buf(outbuf), 0) = 1;
2302 SSVAL(smb_buf(outbuf), 1, nread);
2304 DEBUG(3, ("read fnum=%d num=%d nread=%d\n",
2305 fsp->fnum, (int)numtoread, (int)nread));
2307 return (outsize);
2311 /****************************************************************************
2312 reply to a read and X
2313 ****************************************************************************/
2314 int reply_read_and_X(connection_struct * conn, char *inbuf, char *outbuf,
2315 int length, int bufsize)
2317 files_struct *fsp = file_fsp(inbuf, smb_vwv2);
2318 SMB_OFF_T startpos = IVAL(inbuf, smb_vwv3);
2319 size_t smb_maxcnt = SVAL(inbuf, smb_vwv5);
2320 size_t smb_mincnt = SVAL(inbuf, smb_vwv6);
2321 ssize_t nread = -1;
2322 char *data;
2324 /* If it's an IPC, pass off the pipe handler. */
2325 if (IS_IPC(conn))
2326 return reply_pipe_read_and_X(inbuf, outbuf, length, bufsize);
2328 CHECK_FSP(fsp, conn);
2329 CHECK_READ(fsp);
2330 CHECK_ERROR(fsp);
2332 set_message(outbuf, 12, 0, True);
2333 data = smb_buf(outbuf);
2335 if (CVAL(inbuf, smb_wct) == 12)
2337 #ifdef LARGE_SMB_OFF_T
2339 * This is a large offset (64 bit) read.
2341 startpos |= (((SMB_OFF_T) IVAL(inbuf, smb_vwv10)) << 32);
2343 #else /* !LARGE_SMB_OFF_T */
2346 * Ensure we haven't been sent a >32 bit offset.
2349 if (IVAL(inbuf, smb_vwv10) != 0)
2351 DEBUG(0,
2352 ("reply_read_and_X - large offset (%x << 32) used and we don't support \
2353 64 bit offsets.\n",
2354 (unsigned int)IVAL(inbuf, smb_vwv10)));
2355 return (ERROR(ERRDOS, ERRbadaccess));
2358 #endif /* LARGE_SMB_OFF_T */
2362 if (is_locked
2363 (fsp, conn, (SMB_BIG_UINT) smb_maxcnt, (SMB_BIG_UINT) startpos,
2364 READ_LOCK))
2365 return (ERROR(ERRDOS, ERRlock));
2366 nread = read_file(fsp, data, startpos, smb_maxcnt);
2368 if (nread < 0)
2369 return (UNIXERROR(ERRDOS, ERRnoaccess));
2371 SSVAL(outbuf, smb_vwv5, nread);
2372 SSVAL(outbuf, smb_vwv6, smb_offset(data, outbuf));
2373 SSVAL(smb_buf(outbuf), -2, nread);
2375 DEBUG(3, ("readX fnum=%d min=%d max=%d nread=%d\n",
2376 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread));
2378 return chain_reply(inbuf, outbuf, length, bufsize);
2381 /****************************************************************************
2382 reply to a writebraw (core+ or LANMAN1.0 protocol)
2383 ****************************************************************************/
2385 int reply_writebraw(connection_struct * conn, char *inbuf, char *outbuf,
2386 int size, int dum_buffsize)
2388 ssize_t nwritten = 0;
2389 ssize_t total_written = 0;
2390 size_t numtowrite = 0;
2391 size_t tcount;
2392 SMB_OFF_T startpos;
2393 char *data = NULL;
2394 BOOL write_through;
2395 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
2396 int outsize = 0;
2398 CHECK_FSP(fsp, conn);
2399 CHECK_WRITE(fsp);
2400 CHECK_ERROR(fsp);
2402 tcount = IVAL(inbuf, smb_vwv1);
2403 startpos = IVAL(inbuf, smb_vwv3);
2404 write_through = BITSETW(inbuf + smb_vwv7, 0);
2406 /* We have to deal with slightly different formats depending
2407 on whether we are using the core+ or lanman1.0 protocol */
2408 if (Protocol <= PROTOCOL_COREPLUS)
2410 numtowrite = SVAL(smb_buf(inbuf), -2);
2411 data = smb_buf(inbuf);
2413 else
2415 numtowrite = SVAL(inbuf, smb_vwv10);
2416 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2419 /* force the error type */
2420 CVAL(inbuf, smb_com) = SMBwritec;
2421 CVAL(outbuf, smb_com) = SMBwritec;
2423 if (is_locked
2424 (fsp, conn, (SMB_BIG_UINT) tcount, (SMB_BIG_UINT) startpos,
2425 WRITE_LOCK))
2426 return (ERROR(ERRDOS, ERRlock));
2428 if (numtowrite > 0)
2429 nwritten = write_file(fsp, data, startpos, numtowrite);
2431 DEBUG(3, ("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2432 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten,
2433 (int)write_through));
2435 if (nwritten < numtowrite)
2436 return (UNIXERROR(ERRHRD, ERRdiskfull));
2438 total_written = nwritten;
2440 /* Return a message to the redirector to tell it
2441 to send more bytes */
2442 CVAL(outbuf, smb_com) = SMBwritebraw;
2443 SSVALS(outbuf, smb_vwv0, -1);
2444 outsize =
2445 set_message(outbuf, Protocol > PROTOCOL_COREPLUS ? 1 : 0, 0,
2446 True);
2447 send_smb(smbd_server_fd(), outbuf);
2449 /* Now read the raw data into the buffer and write it */
2450 if (read_smb_length(smbd_server_fd(), inbuf, SMB_SECONDARY_WAIT) ==
2453 exit_server("secondary writebraw failed");
2456 /* Even though this is not an smb message, smb_len
2457 returns the generic length of an smb message */
2458 numtowrite = smb_len(inbuf);
2460 if (tcount > nwritten + numtowrite)
2462 DEBUG(3, ("Client overestimated the write %d %d %d\n",
2463 (int)tcount, (int)nwritten, (int)numtowrite));
2466 nwritten = vfs_transfer_file(smbd_server_fd(), NULL, -1, fsp,
2467 (SMB_OFF_T) numtowrite, NULL, 0,
2468 startpos + nwritten);
2469 total_written += nwritten;
2471 /* Set up outbuf to return the correct return */
2472 outsize = set_message(outbuf, 1, 0, True);
2473 CVAL(outbuf, smb_com) = SMBwritec;
2474 SSVAL(outbuf, smb_vwv0, total_written);
2476 if (nwritten < (ssize_t) numtowrite)
2478 CVAL(outbuf, smb_rcls) = ERRHRD;
2479 SSVAL(outbuf, smb_err, ERRdiskfull);
2482 if ((lp_syncalways(SNUM(conn)) || write_through) &&
2483 lp_strict_sync(SNUM(conn)))
2484 conn->vfs_ops.fsync(fsp->fd);
2486 DEBUG(3, ("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2487 fsp->fnum, (double)startpos, (int)numtowrite,
2488 (int)total_written));
2490 /* we won't return a status if write through is not selected - this
2491 follows what WfWg does */
2492 if (!write_through && total_written == tcount)
2493 return (-1);
2495 return (outsize);
2498 /****************************************************************************
2499 reply to a writeunlock (core+)
2500 ****************************************************************************/
2502 int reply_writeunlock(connection_struct * conn, char *inbuf, char *outbuf,
2503 int size, int dum_buffsize)
2505 ssize_t nwritten = -1;
2506 size_t numtowrite;
2507 SMB_OFF_T startpos;
2508 char *data;
2509 int eclass;
2510 uint32 ecode;
2511 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
2512 int outsize = 0;
2514 CHECK_FSP(fsp, conn);
2515 CHECK_WRITE(fsp);
2516 CHECK_ERROR(fsp);
2518 numtowrite = SVAL(inbuf, smb_vwv1);
2519 startpos = IVAL(inbuf, smb_vwv2);
2520 data = smb_buf(inbuf) + 3;
2522 if (is_locked
2523 (fsp, conn, (SMB_BIG_UINT) numtowrite, (SMB_BIG_UINT) startpos,
2524 WRITE_LOCK))
2525 return (ERROR(ERRDOS, ERRlock));
2527 /* The special X/Open SMB protocol handling of
2528 zero length writes is *NOT* done for
2529 this call */
2530 if (numtowrite == 0)
2531 nwritten = 0;
2532 else
2533 nwritten = write_file(fsp, data, startpos, numtowrite);
2535 if (lp_syncalways(SNUM(conn)))
2536 conn->vfs_ops.fsync(fsp->fd);
2538 if (((nwritten == 0) && (numtowrite != 0)) || (nwritten < 0))
2539 return (UNIXERROR(ERRDOS, ERRnoaccess));
2541 if (!do_unlock
2542 (fsp, conn, (SMB_BIG_UINT) numtowrite, (SMB_BIG_UINT) startpos,
2543 &eclass, &ecode))
2544 return (ERROR(eclass, ecode));
2546 outsize = set_message(outbuf, 1, 0, True);
2548 SSVAL(outbuf, smb_vwv0, nwritten);
2550 DEBUG(3, ("writeunlock fnum=%d num=%d wrote=%d\n",
2551 fsp->fnum, (int)numtowrite, (int)nwritten));
2553 return (outsize);
2556 /****************************************************************************
2557 reply to a write
2558 ****************************************************************************/
2559 int reply_write(connection_struct * conn, char *inbuf, char *outbuf, int size,
2560 int dum_buffsize)
2562 size_t numtowrite;
2563 ssize_t nwritten = -1;
2564 SMB_OFF_T startpos;
2565 char *data;
2566 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
2567 int outsize = 0;
2569 /* If it's an IPC, pass off the pipe handler. */
2570 if (IS_IPC(conn))
2571 return reply_pipe_write(inbuf, outbuf, size, dum_buffsize);
2573 CHECK_FSP(fsp, conn);
2574 CHECK_WRITE(fsp);
2575 CHECK_ERROR(fsp);
2577 numtowrite = SVAL(inbuf, smb_vwv1);
2578 startpos = IVAL(inbuf, smb_vwv2);
2579 data = smb_buf(inbuf) + 3;
2581 if (is_locked
2582 (fsp, conn, (SMB_BIG_UINT) numtowrite, (SMB_BIG_UINT) startpos,
2583 WRITE_LOCK))
2584 return (ERROR(ERRDOS, ERRlock));
2586 /* X/Open SMB protocol says that if smb_vwv1 is
2587 zero then the file size should be extended or
2588 truncated to the size given in smb_vwv[2-3] */
2589 if (numtowrite == 0)
2591 if ((nwritten = set_filelen(fsp->fd, (SMB_OFF_T) startpos)) >= 0) /* tpot vfs */
2592 set_filelen_write_cache(fsp, startpos);
2594 else
2595 nwritten = write_file(fsp, data, startpos, numtowrite);
2597 if (lp_syncalways(SNUM(conn)))
2598 conn->vfs_ops.fsync(fsp->fd);
2600 if (((nwritten == 0) && (numtowrite != 0)) || (nwritten < 0))
2601 return (UNIXERROR(ERRDOS, ERRnoaccess));
2603 outsize = set_message(outbuf, 1, 0, True);
2605 SSVAL(outbuf, smb_vwv0, nwritten);
2607 if (nwritten < (ssize_t) numtowrite)
2609 CVAL(outbuf, smb_rcls) = ERRHRD;
2610 SSVAL(outbuf, smb_err, ERRdiskfull);
2613 DEBUG(3, ("write fnum=%d num=%d wrote=%d\n",
2614 fsp->fnum, (int)numtowrite, (int)nwritten));
2616 return (outsize);
2620 /****************************************************************************
2621 reply to a write and X
2622 ****************************************************************************/
2623 int reply_write_and_X(connection_struct * conn, char *inbuf, char *outbuf,
2624 int length, int bufsize)
2626 files_struct *fsp = file_fsp(inbuf, smb_vwv2);
2627 SMB_OFF_T startpos = IVAL(inbuf, smb_vwv3);
2628 size_t numtowrite = SVAL(inbuf, smb_vwv10);
2629 BOOL write_through = BITSETW(inbuf + smb_vwv7, 0);
2630 ssize_t nwritten = -1;
2631 unsigned int smb_doff = SVAL(inbuf, smb_vwv11);
2632 char *data;
2634 /* If it's an IPC, pass off the pipe handler. */
2635 if (IS_IPC(conn))
2636 return reply_pipe_write_and_X(inbuf, outbuf, length, bufsize);
2638 CHECK_FSP(fsp, conn);
2639 CHECK_WRITE(fsp);
2640 CHECK_ERROR(fsp);
2642 if(smb_doff > smb_len(inbuf))
2643 return(ERROR(ERRDOS,ERRbadmem));
2645 data = smb_base(inbuf) + smb_doff;
2647 if (CVAL(inbuf, smb_wct) == 14)
2649 #ifdef LARGE_SMB_OFF_T
2651 * This is a large offset (64 bit) write.
2653 startpos |= (((SMB_OFF_T) IVAL(inbuf, smb_vwv12)) << 32);
2655 #else /* !LARGE_SMB_OFF_T */
2658 * Ensure we haven't been sent a >32 bit offset.
2661 if (IVAL(inbuf, smb_vwv12) != 0)
2663 DEBUG(0,
2664 ("reply_write_and_X - large offset (%x << 32) used and we don't support \
2665 64 bit offsets.\n",
2666 (unsigned int)IVAL(inbuf, smb_vwv12)));
2667 return (ERROR(ERRDOS, ERRbadaccess));
2670 #endif /* LARGE_SMB_OFF_T */
2673 if (is_locked
2674 (fsp, conn, (SMB_BIG_UINT) numtowrite, (SMB_BIG_UINT) startpos,
2675 WRITE_LOCK))
2676 return (ERROR(ERRDOS, ERRlock));
2678 /* X/Open SMB protocol says that, unlike SMBwrite
2679 if the length is zero then NO truncation is
2680 done, just a write of zero. To truncate a file,
2681 use SMBwrite. */
2682 if (numtowrite == 0)
2683 nwritten = 0;
2684 else
2685 nwritten = write_file(fsp, data, startpos, numtowrite);
2687 if (((nwritten == 0) && (numtowrite != 0)) || (nwritten < 0))
2688 return (UNIXERROR(ERRDOS, ERRnoaccess));
2690 set_message(outbuf, 6, 0, True);
2692 SSVAL(outbuf, smb_vwv2, nwritten);
2694 if (nwritten < (ssize_t) numtowrite)
2696 CVAL(outbuf, smb_rcls) = ERRHRD;
2697 SSVAL(outbuf, smb_err, ERRdiskfull);
2700 DEBUG(3, ("writeX fnum=%d num=%d wrote=%d\n",
2701 fsp->fnum, (int)numtowrite, (int)nwritten));
2703 if (lp_syncalways(SNUM(conn)) || write_through)
2704 conn->vfs_ops.fsync(fsp->fd);
2706 return chain_reply(inbuf, outbuf, length, bufsize);
2710 /****************************************************************************
2711 reply to a lseek
2712 ****************************************************************************/
2714 int reply_lseek(connection_struct * conn, char *inbuf, char *outbuf, int size,
2715 int dum_buffsize)
2717 SMB_OFF_T startpos;
2718 SMB_OFF_T res = -1;
2719 int mode, umode;
2720 int outsize = 0;
2721 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
2723 CHECK_FSP(fsp, conn);
2724 CHECK_ERROR(fsp);
2726 flush_write_cache(fsp, SEEK_FLUSH);
2728 mode = SVAL(inbuf, smb_vwv1) & 3;
2729 startpos = IVALS(inbuf, smb_vwv2);
2731 switch (mode)
2733 case 0:
2734 umode = SEEK_SET;
2735 break;
2736 case 1:
2737 umode = SEEK_CUR;
2738 break;
2739 case 2:
2740 umode = SEEK_END;
2741 break;
2742 default:
2743 umode = SEEK_SET;
2744 break;
2747 if ((res = conn->vfs_ops.lseek(fsp->fd, startpos, umode)) == -1)
2750 * Check for the special case where a seek before the start
2751 * of the file sets the offset to zero. Added in the CIFS spec,
2752 * section 4.2.7.
2755 if (errno == EINVAL)
2757 SMB_OFF_T current_pos = startpos;
2759 if (umode == SEEK_CUR)
2762 if (
2763 (current_pos =
2764 conn->vfs_ops.lseek(fsp->fd, 0,
2765 SEEK_CUR)) == -1)
2766 return (UNIXERROR
2767 (ERRDOS, ERRnoaccess));
2769 current_pos += startpos;
2772 else if (umode == SEEK_END)
2775 SMB_STRUCT_STAT sbuf;
2777 if (conn->vfs_ops.fstat(fsp->fd, &sbuf) == -1)
2778 return (UNIXERROR
2779 (ERRDOS, ERRnoaccess));
2781 current_pos += sbuf.st_size;
2784 if (current_pos < 0)
2785 res =
2786 conn->vfs_ops.lseek(fsp->fd, 0,
2787 SEEK_SET);
2790 if (res == -1)
2791 return (UNIXERROR(ERRDOS, ERRnoaccess));
2794 fsp->pos = res;
2796 outsize = set_message(outbuf, 2, 0, True);
2797 SIVAL(outbuf, smb_vwv0, res);
2799 DEBUG(3, ("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2800 fsp->fnum, (double)startpos, (double)res, mode));
2802 return (outsize);
2805 /****************************************************************************
2806 reply to a flush
2807 ****************************************************************************/
2809 int reply_flush(connection_struct * conn, char *inbuf, char *outbuf, int size,
2810 int dum_buffsize)
2812 int outsize = set_message(outbuf, 0, 0, True);
2813 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
2815 if (fsp)
2817 CHECK_FSP(fsp, conn);
2818 CHECK_ERROR(fsp);
2821 if (!fsp)
2823 file_sync_all(conn);
2825 else
2827 conn->vfs_ops.fsync(fsp->fd);
2830 DEBUG(3, ("flush\n"));
2831 return (outsize);
2835 /****************************************************************************
2836 reply to a exit
2837 ****************************************************************************/
2838 int reply_exit(connection_struct * conn,
2839 char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
2841 int outsize = set_message(outbuf, 0, 0, True);
2842 DEBUG(3, ("exit\n"));
2844 return (outsize);
2848 /****************************************************************************
2849 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2850 ****************************************************************************/
2851 int reply_close(connection_struct * conn, char *inbuf, char *outbuf, int size,
2852 int dum_buffsize)
2854 int outsize = 0;
2855 time_t mtime;
2856 int32 eclass = 0, err = 0;
2857 files_struct *fsp = NULL;
2859 outsize = set_message(outbuf, 0, 0, True);
2861 /* If it's an IPC, pass off to the pipe handler. */
2862 if (IS_IPC(conn))
2863 return reply_pipe_close(conn, inbuf, outbuf);
2865 fsp = file_fsp(inbuf, smb_vwv0);
2868 * We can only use CHECK_FSP if we know it's not a directory.
2871 if (!fsp || (fsp->conn != conn))
2872 return (ERROR(ERRDOS, ERRbadfid));
2874 if (HAS_CACHED_ERROR(fsp))
2876 eclass = fsp->wbmpx_ptr->wr_errclass;
2877 err = fsp->wbmpx_ptr->wr_error;
2880 if (fsp->is_directory || fsp->stat_open)
2883 * Special case - close NT SMB directory or stat file
2884 * handle.
2886 DEBUG(3,
2887 ("close %s fnum=%d\n",
2888 fsp->is_directory ? "directory" : "stat file open",
2889 fsp->fnum));
2890 close_file(fsp, True);
2892 else
2895 * Close ordinary file.
2897 int close_err;
2900 * If there was a modify time outstanding,
2901 * try and set it here.
2903 if (fsp->pending_modtime)
2904 set_filetime(conn, fsp->fsp_name,
2905 fsp->pending_modtime);
2908 * Now take care of any time sent in the close.
2910 mtime = make_unix_date3(inbuf + smb_vwv1);
2912 /* try and set the date */
2913 set_filetime(conn, fsp->fsp_name, mtime);
2915 DEBUG(3, ("close fd=%d fnum=%d (numopen=%d)\n",
2916 fsp->fd, fsp->fnum, conn->num_files_open));
2919 * close_file() returns the unix errno if an error
2920 * was detected on close - normally this is due to
2921 * a disk full error. If not then it was probably an I/O error.
2924 if ((close_err = close_file(fsp, True)) != 0)
2926 errno = close_err;
2927 return (UNIXERROR(ERRHRD, ERRgeneral));
2931 /* We have a cached error */
2932 if (eclass || err)
2933 return (ERROR(eclass, err));
2935 return (outsize);
2939 /****************************************************************************
2940 reply to a writeclose (Core+ protocol)
2941 ****************************************************************************/
2943 int reply_writeclose(connection_struct * conn,
2944 char *inbuf, char *outbuf, int size, int dum_buffsize)
2946 size_t numtowrite;
2947 ssize_t nwritten = -1;
2948 int outsize = 0;
2949 int close_err = 0;
2950 SMB_OFF_T startpos;
2951 char *data;
2952 time_t mtime;
2953 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
2955 CHECK_FSP(fsp, conn);
2956 CHECK_WRITE(fsp);
2957 CHECK_ERROR(fsp);
2959 numtowrite = SVAL(inbuf, smb_vwv1);
2960 startpos = IVAL(inbuf, smb_vwv2);
2961 mtime = make_unix_date3(inbuf + smb_vwv4);
2962 data = smb_buf(inbuf) + 1;
2964 if (is_locked
2965 (fsp, conn, (SMB_BIG_UINT) numtowrite, (SMB_BIG_UINT) startpos,
2966 WRITE_LOCK))
2967 return (ERROR(ERRDOS, ERRlock));
2969 nwritten = write_file(fsp, data, startpos, numtowrite);
2971 set_filetime(conn, fsp->fsp_name, mtime);
2973 close_err = close_file(fsp, True);
2975 DEBUG(3, ("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2976 fsp->fnum, (int)numtowrite, (int)nwritten,
2977 conn->num_files_open));
2979 if (nwritten <= 0)
2980 return (UNIXERROR(ERRDOS, ERRnoaccess));
2982 if (close_err != 0)
2984 errno = close_err;
2985 return (UNIXERROR(ERRHRD, ERRgeneral));
2988 outsize = set_message(outbuf, 1, 0, True);
2990 SSVAL(outbuf, smb_vwv0, nwritten);
2991 return (outsize);
2995 /****************************************************************************
2996 reply to a lock
2997 ****************************************************************************/
2998 int reply_lock(connection_struct * conn,
2999 char *inbuf, char *outbuf, int length, int dum_buffsize)
3001 int outsize = set_message(outbuf, 0, 0, True);
3002 SMB_BIG_UINT count, offset;
3003 int eclass;
3004 uint32 ecode;
3005 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
3007 CHECK_FSP(fsp, conn);
3008 CHECK_ERROR(fsp);
3010 count = (SMB_BIG_UINT) IVAL(inbuf, smb_vwv1);
3011 offset = (SMB_BIG_UINT) IVAL(inbuf, smb_vwv3);
3013 DEBUG(3, ("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3014 fsp->fd, fsp->fnum, (double)offset, (double)count));
3016 if (!do_lock(fsp, conn, count, offset, WRITE_LOCK, &eclass, &ecode))
3018 if ((ecode == ERRlock) && lp_blocking_locks(SNUM(conn)))
3021 * A blocking lock was requested. Package up
3022 * this smb into a queued request and push it
3023 * onto the blocking lock queue.
3025 if (push_blocking_lock_request(inbuf, length, -1, 0))
3026 return -1;
3028 return (ERROR(eclass, ecode));
3031 return (outsize);
3035 /****************************************************************************
3036 reply to a unlock
3037 ****************************************************************************/
3038 int reply_unlock(connection_struct * conn, char *inbuf, char *outbuf,
3039 int size, int dum_buffsize)
3041 int outsize = set_message(outbuf, 0, 0, True);
3042 SMB_BIG_UINT count, offset;
3043 int eclass;
3044 uint32 ecode;
3045 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
3047 CHECK_FSP(fsp, conn);
3048 CHECK_ERROR(fsp);
3050 count = (SMB_BIG_UINT) IVAL(inbuf, smb_vwv1);
3051 offset = (SMB_BIG_UINT) IVAL(inbuf, smb_vwv3);
3053 if (!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
3054 return (ERROR(eclass, ecode));
3056 DEBUG(3, ("unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3057 fsp->fd, fsp->fnum, (double)offset, (double)count));
3059 return (outsize);
3063 /****************************************************************************
3064 reply to a tdis
3065 ****************************************************************************/
3066 int reply_tdis(connection_struct * conn,
3067 char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
3069 int outsize = set_message(outbuf, 0, 0, True);
3070 uint16 vuid;
3072 vuid = SVAL(inbuf, smb_uid);
3074 if (!conn)
3076 DEBUG(4, ("Invalid connection in tdis\n"));
3077 return (ERROR(ERRSRV, ERRinvnid));
3080 conn->used = False;
3082 close_cnum(conn, vuid);
3084 return outsize;
3089 /****************************************************************************
3090 reply to a echo
3091 ****************************************************************************/
3092 int reply_echo(connection_struct * conn,
3093 char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
3095 int smb_reverb = SVAL(inbuf, smb_vwv0);
3096 int seq_num;
3097 unsigned int data_len = smb_buflen(inbuf);
3098 int outsize = set_message(outbuf, 1, data_len, True);
3100 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
3102 /* copy any incoming data back out */
3103 if (data_len > 0)
3104 memcpy(smb_buf(outbuf), smb_buf(inbuf), data_len);
3106 if (smb_reverb > 100)
3108 DEBUG(0,
3109 ("large reverb (%d)?? Setting to 100\n", smb_reverb));
3110 smb_reverb = 100;
3113 for (seq_num = 1; seq_num <= smb_reverb; seq_num++)
3115 SSVAL(outbuf, smb_vwv0, seq_num);
3117 smb_setlen(outbuf, outsize - 4);
3119 send_smb(smbd_server_fd(), outbuf);
3122 DEBUG(3, ("echo %d times\n", smb_reverb));
3124 smb_echo_count++;
3126 return -1;
3130 /****************************************************************************
3131 reply to a printopen
3132 ****************************************************************************/
3133 int reply_printopen(connection_struct * conn,
3134 char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
3136 int outsize = 0;
3137 files_struct *fsp;
3139 if (!CAN_PRINT(conn))
3140 return (ERROR(ERRDOS, ERRnoaccess));
3142 /* Open for exclusive use, write only. */
3143 fsp = print_fsp_open(conn, "dos.prn");
3145 if (!fsp)
3147 return (UNIXERROR(ERRDOS, ERRnoaccess));
3150 outsize = set_message(outbuf, 1, 0, True);
3151 SSVAL(outbuf, smb_vwv0, fsp->fnum);
3153 DEBUG(3, ("openprint fd=%d fnum=%d\n", fsp->fd, fsp->fnum));
3155 return (outsize);
3159 /****************************************************************************
3160 reply to a printclose
3161 ****************************************************************************/
3162 int reply_printclose(connection_struct * conn,
3163 char *inbuf, char *outbuf, int dum_size,
3164 int dum_buffsize)
3166 int outsize = set_message(outbuf, 0, 0, True);
3167 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
3168 int close_err = 0;
3170 CHECK_FSP(fsp, conn);
3171 CHECK_ERROR(fsp);
3173 if (!CAN_PRINT(conn))
3174 return (ERROR(ERRDOS, ERRnoaccess));
3176 DEBUG(3, ("printclose fd=%d fnum=%d\n", fsp->fd, fsp->fnum));
3178 close_err = close_file(fsp, True);
3180 if (close_err != 0)
3182 errno = close_err;
3183 return (UNIXERROR(ERRHRD, ERRgeneral));
3186 return (outsize);
3190 /****************************************************************************
3191 reply to a printqueue
3192 ****************************************************************************/
3193 int reply_printqueue(connection_struct * conn,
3194 char *inbuf, char *outbuf, int dum_size,
3195 int dum_buffsize)
3197 int outsize = set_message(outbuf, 2, 3, True);
3198 int max_count = SVAL(inbuf, smb_vwv0);
3199 int start_index = SVAL(inbuf, smb_vwv1);
3201 /* we used to allow the client to get the cnum wrong, but that
3202 is really quite gross and only worked when there was only
3203 one printer - I think we should now only accept it if they
3204 get it right (tridge) */
3205 if (!CAN_PRINT(conn))
3206 return (ERROR(ERRDOS, ERRnoaccess));
3208 SSVAL(outbuf, smb_vwv0, 0);
3209 SSVAL(outbuf, smb_vwv1, 0);
3210 CVAL(smb_buf(outbuf), 0) = 1;
3211 SSVAL(smb_buf(outbuf), 1, 0);
3213 DEBUG(3, ("printqueue start_index=%d max_count=%d\n",
3214 start_index, max_count));
3217 print_queue_struct *queue = NULL;
3218 char *p = smb_buf(outbuf) + 3;
3219 int count = print_queue_status(SNUM(conn), &queue, NULL);
3220 int num_to_get = ABS(max_count);
3221 int first =
3222 (max_count >
3223 0 ? start_index : start_index + max_count + 1);
3224 int i;
3226 if (first >= count)
3227 num_to_get = 0;
3228 else
3229 num_to_get = MIN(num_to_get, count - first);
3232 for (i = first; i < first + num_to_get; i++)
3234 put_dos_date2(p, 0, queue[i].time);
3235 CVAL(p, 4) =
3236 (queue[i].status == LPQ_PRINTING ? 2 : 3);
3237 SSVAL(p, 5, queue[i].job);
3238 SIVAL(p, 7, queue[i].size);
3239 CVAL(p, 11) = 0;
3240 StrnCpy(p + 12, queue[i].user, 16);
3241 p += 28;
3244 if (count > 0)
3246 outsize =
3247 set_message(outbuf, 2, 28 * count + 3, False);
3248 SSVAL(outbuf, smb_vwv0, count);
3249 SSVAL(outbuf, smb_vwv1,
3250 (max_count > 0 ? first + count : first - 1));
3251 CVAL(smb_buf(outbuf), 0) = 1;
3252 SSVAL(smb_buf(outbuf), 1, 28 * count);
3255 if (queue)
3256 free(queue);
3258 DEBUG(3, ("%d entries returned in queue\n", count));
3261 return (outsize);
3265 /****************************************************************************
3266 reply to a printwrite
3267 ****************************************************************************/
3268 int reply_printwrite(connection_struct * conn, char *inbuf, char *outbuf,
3269 int dum_size, int dum_buffsize)
3271 int numtowrite;
3272 int outsize = set_message(outbuf, 0, 0, True);
3273 char *data;
3274 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
3276 if (!CAN_PRINT(conn))
3277 return (ERROR(ERRDOS, ERRnoaccess));
3279 CHECK_FSP(fsp, conn);
3280 CHECK_WRITE(fsp);
3281 CHECK_ERROR(fsp);
3283 numtowrite = SVAL(smb_buf(inbuf), 1);
3284 data = smb_buf(inbuf) + 3;
3286 if (write_file(fsp, data, -1, numtowrite) != numtowrite)
3287 return (UNIXERROR(ERRDOS, ERRnoaccess));
3289 DEBUG(3, ("printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite));
3291 return (outsize);
3295 /****************************************************************************
3296 reply to a mkdir
3297 ****************************************************************************/
3298 int reply_mkdir(connection_struct * conn, char *inbuf, char *outbuf,
3299 int dum_size, int dum_buffsize)
3301 pstring directory;
3302 int outsize, ret = -1;
3303 BOOL bad_path = False;
3305 pstrcpy(directory, smb_buf(inbuf) + 1);
3306 unix_convert(directory, conn, 0, &bad_path, NULL);
3308 if (check_name(directory, conn))
3309 ret = conn->vfs_ops.mkdir(dos_to_unix(directory, False),
3310 unix_mode(conn, aDIR, directory));
3312 if (ret < 0)
3314 if ((errno == ENOENT) && bad_path)
3316 unix_ERR_class = ERRDOS;
3317 unix_ERR_code = ERRbadpath;
3319 return (UNIXERROR(ERRDOS, ERRnoaccess));
3322 outsize = set_message(outbuf, 0, 0, True);
3324 DEBUG(3, ("mkdir %s ret=%d\n", directory, ret));
3326 return (outsize);
3329 /****************************************************************************
3330 Static function used by reply_rmdir to delete an entire directory
3331 tree recursively.
3332 ****************************************************************************/
3333 static BOOL recursive_rmdir(connection_struct * conn, char *directory)
3335 char *dname = NULL;
3336 BOOL ret = False;
3337 void *dirptr = OpenDir(NULL, directory, False);
3339 if (dirptr == NULL)
3340 return True;
3342 while ((dname = ReadDirName(dirptr)))
3344 pstring fullname;
3345 SMB_STRUCT_STAT st;
3347 if ((strcmp(dname, ".") == 0) || (strcmp(dname, "..") == 0))
3348 continue;
3350 /* Construct the full name. */
3351 if (strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
3353 errno = ENOMEM;
3354 ret = True;
3355 break;
3357 pstrcpy(fullname, directory);
3358 pstrcat(fullname, "/");
3359 pstrcat(fullname, dname);
3361 if (conn->vfs_ops.lstat(dos_to_unix(fullname, False), &st) !=
3364 ret = True;
3365 break;
3368 if (st.st_mode & S_IFDIR)
3370 if (recursive_rmdir(conn, fullname) != 0)
3372 ret = True;
3373 break;
3375 if (conn->vfs_ops.
3376 rmdir(dos_to_unix(fullname, False)) != 0)
3378 ret = True;
3379 break;
3382 else if (conn->vfs_ops.unlink(dos_to_unix(fullname, False)) !=
3385 ret = True;
3386 break;
3389 CloseDir(dirptr);
3390 return ret;
3393 /****************************************************************************
3394 The internals of the rmdir code - called elsewhere.
3395 ****************************************************************************/
3397 BOOL rmdir_internals(connection_struct * conn, char *directory)
3399 BOOL ok;
3401 ok = (conn->vfs_ops.rmdir(dos_to_unix(directory, False)) == 0);
3402 if (!ok && ((errno == ENOTEMPTY) || (errno == EEXIST))
3403 && lp_veto_files(SNUM(conn)))
3406 * Check to see if the only thing in this directory are
3407 * vetoed files/directories. If so then delete them and
3408 * retry. If we fail to delete any of them (and we *don't*
3409 * do a recursive delete) then fail the rmdir.
3411 BOOL all_veto_files = True;
3412 char *dname;
3413 void *dirptr = OpenDir(conn, directory, False);
3415 if (dirptr != NULL)
3417 int dirpos = TellDir(dirptr);
3418 while ((dname = ReadDirName(dirptr)))
3420 if ((strcmp(dname, ".") == 0)
3421 || (strcmp(dname, "..") == 0))
3422 continue;
3423 if (!IS_VETO_PATH(conn, dname))
3425 all_veto_files = False;
3426 break;
3429 if (all_veto_files)
3431 SeekDir(dirptr, dirpos);
3432 while ((dname = ReadDirName(dirptr)))
3434 pstring fullname;
3435 SMB_STRUCT_STAT st;
3437 if ((strcmp(dname, ".") == 0)
3438 || (strcmp(dname, "..") == 0))
3439 continue;
3441 /* Construct the full name. */
3442 if (strlen(directory) +
3443 strlen(dname) + 1 >=
3444 sizeof(fullname))
3446 errno = ENOMEM;
3447 break;
3449 pstrcpy(fullname, directory);
3450 pstrcat(fullname, "/");
3451 pstrcat(fullname, dname);
3453 if (conn->vfs_ops.
3454 lstat(dos_to_unix
3455 (fullname, False),
3456 &st) != 0)
3457 break;
3458 if (st.st_mode & S_IFDIR)
3460 if (lp_recursive_veto_delete
3461 (SNUM(conn)))
3463 if (recursive_rmdir
3464 (conn,
3465 fullname) != 0)
3466 break;
3468 if (conn->vfs_ops.
3469 rmdir(dos_to_unix
3470 (fullname,
3471 False)) != 0)
3472 break;
3474 else if (conn->vfs_ops.
3475 unlink(dos_to_unix
3476 (fullname,
3477 False)) != 0)
3478 break;
3480 CloseDir(dirptr);
3481 /* Retry the rmdir */
3482 ok =
3483 (conn->vfs_ops.
3484 rmdir(dos_to_unix(directory, False)) ==
3487 else
3488 CloseDir(dirptr);
3490 else
3491 errno = ENOTEMPTY;
3494 if (!ok)
3495 DEBUG(3,
3496 ("rmdir_internals: couldn't remove directory %s : %s\n",
3497 directory, strerror(errno)));
3499 return ok;
3502 /****************************************************************************
3503 Reply to a rmdir.
3504 ****************************************************************************/
3506 int reply_rmdir(connection_struct * conn, char *inbuf, char *outbuf,
3507 int dum_size, int dum_buffsize)
3509 pstring directory;
3510 int outsize = 0;
3511 BOOL ok = False;
3512 BOOL bad_path = False;
3514 pstrcpy(directory, smb_buf(inbuf) + 1);
3516 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3517 unix_convert(directory, conn, NULL, &bad_path, NULL);
3519 if (check_name(directory, conn))
3521 dptr_closepath(directory, SVAL(inbuf, smb_pid));
3522 ok = rmdir_internals(conn, directory);
3525 if (!ok)
3527 if ((errno == ENOENT) && bad_path)
3529 unix_ERR_class = ERRDOS;
3530 unix_ERR_code = ERRbadpath;
3532 return (UNIXERROR(ERRDOS, ERRbadpath));
3535 outsize = set_message(outbuf, 0, 0, True);
3537 DEBUG(3, ("rmdir %s\n", directory));
3539 return (outsize);
3543 /*******************************************************************
3544 resolve wildcards in a filename rename
3545 ********************************************************************/
3546 static BOOL resolve_wildcards(char *name1, char *name2)
3548 fstring root1, root2;
3549 fstring ext1, ext2;
3550 char *p, *p2;
3552 name1 = strrchr(name1, '/');
3553 name2 = strrchr(name2, '/');
3555 if (!name1 || !name2)
3556 return (False);
3558 fstrcpy(root1, name1);
3559 fstrcpy(root2, name2);
3560 p = strrchr(root1, '.');
3561 if (p)
3563 *p = 0;
3564 fstrcpy(ext1, p + 1);
3566 else
3568 fstrcpy(ext1, "");
3570 p = strrchr(root2, '.');
3571 if (p)
3573 *p = 0;
3574 fstrcpy(ext2, p + 1);
3576 else
3578 fstrcpy(ext2, "");
3581 p = root1;
3582 p2 = root2;
3583 while (*p2)
3585 if (*p2 == '?')
3587 *p2 = *p;
3588 p2++;
3590 else
3592 p2++;
3594 if (*p)
3595 p++;
3598 p = ext1;
3599 p2 = ext2;
3600 while (*p2)
3602 if (*p2 == '?')
3604 *p2 = *p;
3605 p2++;
3607 else
3609 p2++;
3611 if (*p)
3612 p++;
3615 pstrcpy(name2, root2);
3616 if (ext2[0])
3618 pstrcat(name2, ".");
3619 pstrcat(name2, ext2);
3622 return (True);
3625 /*******************************************************************
3626 check if a user is allowed to rename a file
3627 ********************************************************************/
3628 static BOOL can_rename(char *fname, connection_struct * conn)
3630 SMB_STRUCT_STAT sbuf;
3632 if (!CAN_WRITE(conn))
3633 return (False);
3635 if (conn->vfs_ops.lstat(dos_to_unix(fname, False), &sbuf) != 0)
3636 return (False);
3637 if (!check_file_sharing(conn, fname, True))
3638 return (False);
3640 return (True);
3643 /****************************************************************************
3644 The guts of the rename command, split out so it may be called by the NT SMB
3645 code.
3646 ****************************************************************************/
3647 int rename_internals(connection_struct * conn,
3648 char *inbuf, char *outbuf, char *name,
3649 char *newname, BOOL replace_if_exists)
3651 pstring directory;
3652 pstring mask;
3653 pstring newname_last_component;
3654 char *p;
3655 BOOL has_wild;
3656 BOOL bad_path1 = False;
3657 BOOL bad_path2 = False;
3658 int count = 0;
3659 int error = ERRnoaccess;
3660 BOOL exists = False;
3661 BOOL rc = True;
3662 pstring zdirectory;
3664 *directory = *mask = 0;
3666 rc = unix_convert(name, conn, 0, &bad_path1, NULL);
3667 unix_convert(newname, conn, newname_last_component, &bad_path2, NULL);
3670 * Split the old name into directory and last component
3671 * strings. Note that unix_convert may have stripped off a
3672 * leading ./ from both name and newname if the rename is
3673 * at the root of the share. We need to make sure either both
3674 * name and newname contain a / character or neither of them do
3675 * as this is checked in resolve_wildcards().
3678 p = strrchr(name, '/');
3679 if (!p)
3681 pstrcpy(directory, ".");
3682 pstrcpy(mask, name);
3684 else
3686 *p = 0;
3687 pstrcpy(directory, name);
3688 pstrcpy(mask, p + 1);
3689 *p = '/'; /* Replace needed for exceptional test below. */
3693 * We should only check the mangled cache
3694 * here if unix_convert failed. This means
3695 * that the path in 'mask' doesn't exist
3696 * on the file system and so we need to look
3697 * for a possible mangle. This patch from
3698 * Tine Smukavec <valentin.smukavec@hermes.si>.
3701 if (!rc && is_mangled(mask))
3702 check_mangled_cache(mask);
3704 has_wild = strchr(mask, '*') || strchr(mask, '?');
3706 if (!has_wild)
3709 * No wildcards - just process the one file.
3711 BOOL is_short_name = is_8_3(name, True);
3713 /* Add a terminating '/' to the directory name. */
3714 pstrcat(directory, "/");
3715 pstrcat(directory, mask);
3717 /* Ensure newname contains a '/' also */
3718 if (strrchr(newname, '/') == 0)
3720 pstring tmpstr;
3722 pstrcpy(tmpstr, "./");
3723 pstrcat(tmpstr, newname);
3724 pstrcpy(newname, tmpstr);
3727 DEBUG(3,
3728 ("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3729 case_sensitive, case_preserve, short_case_preserve,
3730 directory, newname, newname_last_component,
3731 is_short_name));
3734 * Check for special case with case preserving and not
3735 * case sensitive, if directory and newname are identical,
3736 * and the old last component differs from the original
3737 * last component only by case, then we should allow
3738 * the rename (user is trying to change the case of the
3739 * filename).
3741 if ((case_sensitive == False) &&
3742 (((case_preserve == True) &&
3743 (is_short_name == False)) ||
3744 ((short_case_preserve == True) &&
3745 (is_short_name == True))) &&
3746 strcsequal(directory, newname))
3748 pstring newname_modified_last_component;
3751 * Get the last component of the modified name.
3752 * Note that we guarantee that newname contains a '/'
3753 * character above.
3755 p = strrchr(newname, '/');
3756 pstrcpy(newname_modified_last_component, p + 1);
3758 if (strcsequal(newname_modified_last_component,
3759 newname_last_component) == False)
3762 * Replace the modified last component with
3763 * the original.
3765 pstrcpy(p + 1, newname_last_component);
3769 pstrcpy(zdirectory, dos_to_unix(directory, False));
3770 if (replace_if_exists)
3773 * NT SMB specific flag - rename can overwrite
3774 * file with the same name so don't check for
3775 * vfs_file_exist().
3777 if (resolve_wildcards(directory, newname) &&
3778 can_rename(directory, conn) &&
3779 !conn->vfs_ops.rename(zdirectory,
3780 dos_to_unix(newname,
3781 False)))
3782 count++;
3784 else
3786 if (resolve_wildcards(directory, newname) &&
3787 can_rename(directory, conn) &&
3788 !vfs_file_exist(conn, newname, NULL) &&
3789 !conn->vfs_ops.rename(zdirectory,
3790 dos_to_unix(newname,
3791 False)))
3792 count++;
3795 DEBUG(3,
3796 ("rename_internals: %s doing rename on %s -> %s\n",
3797 (count != 0) ? "succeeded" : "failed", directory,
3798 newname));
3800 if (!count)
3801 exists = vfs_file_exist(conn, directory, NULL);
3802 if (!count && exists && vfs_file_exist(conn, newname, NULL))
3804 exists = True;
3805 error = ERRrename;
3808 else
3811 * Wildcards - process each file that matches.
3813 void *dirptr = NULL;
3814 char *dname;
3815 pstring destname;
3817 if (check_name(directory, conn))
3818 dirptr = OpenDir(conn, directory, True);
3820 if (dirptr)
3822 error = ERRbadfile;
3824 if (strequal(mask, "????????.???"))
3825 pstrcpy(mask, "*");
3827 while ((dname = ReadDirName(dirptr)))
3829 pstring fname;
3831 pstrcpy(fname, dname);
3833 if (!mask_match
3834 (fname, mask, case_sensitive, False))
3835 continue;
3837 error = ERRnoaccess;
3838 slprintf(fname, sizeof(fname) - 1, "%s/%s",
3839 directory, dname);
3840 if (!can_rename(fname, conn))
3842 DEBUG(6,
3843 ("rename %s refused\n", fname));
3844 continue;
3846 pstrcpy(destname, newname);
3848 if (!resolve_wildcards(fname, destname))
3850 DEBUG(6,
3851 ("resolve_wildcards %s %s failed\n",
3852 fname, destname));
3853 continue;
3856 if (!replace_if_exists &&
3857 vfs_file_exist(conn, destname, NULL))
3859 DEBUG(6,
3860 ("file_exist %s\n", destname));
3861 error = 183;
3862 continue;
3865 if (!conn->vfs_ops.
3866 rename(dos_to_unix(fname, False),
3867 dos_to_unix(destname, False)))
3868 count++;
3869 DEBUG(3,
3870 ("rename_internals: doing rename on %s -> %s\n",
3871 fname, destname));
3873 CloseDir(dirptr);
3877 if (count == 0)
3879 if (exists)
3880 return (ERROR(ERRDOS, error));
3881 else
3883 if ((errno == ENOENT) && (bad_path1 || bad_path2))
3885 unix_ERR_class = ERRDOS;
3886 unix_ERR_code = ERRbadpath;
3888 return (UNIXERROR(ERRDOS, error));
3892 return 0;
3895 /****************************************************************************
3896 Reply to a mv.
3897 ****************************************************************************/
3899 int reply_mv(connection_struct * conn, char *inbuf, char *outbuf,
3900 int dum_size, int dum_buffsize)
3902 int outsize = 0;
3903 pstring name;
3904 pstring newname;
3906 pstrcpy(name, smb_buf(inbuf) + 1);
3907 pstrcpy(newname, smb_buf(inbuf) + 3 + strlen(name));
3909 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3910 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3912 DEBUG(3, ("reply_mv : %s -> %s\n", name, newname));
3914 outsize = rename_internals(conn, inbuf, outbuf, name, newname, False);
3915 if (outsize == 0)
3916 outsize = set_message(outbuf, 0, 0, True);
3918 return (outsize);
3921 /*******************************************************************
3922 copy a file as part of a reply_copy
3923 ******************************************************************/
3925 static BOOL copy_file(char *src, char *dest1, connection_struct * conn,
3926 int ofun, int count, BOOL target_is_directory,
3927 int *err_ret)
3929 int Access, action;
3930 SMB_STRUCT_STAT st;
3931 SMB_OFF_T ret = -1;
3932 files_struct *fsp1, *fsp2;
3933 pstring dest;
3935 *err_ret = 0;
3937 pstrcpy(dest, dest1);
3938 if (target_is_directory)
3940 char *p = strrchr(src, '/');
3941 if (p)
3942 p++;
3943 else
3944 p = src;
3945 pstrcat(dest, "/");
3946 pstrcat(dest, p);
3949 if (!vfs_file_exist(conn, src, &st))
3950 return (False);
3952 fsp1 =
3953 open_file_shared(conn, src,
3954 SET_DENY_MODE(DENY_NONE) |
3955 SET_OPEN_MODE(DOS_OPEN_RDONLY),
3956 (FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN),
3957 0, 0, &Access, &action);
3959 if (!fsp1)
3961 return (False);
3964 if (!target_is_directory && count)
3965 ofun = 1;
3967 fsp2 =
3968 open_file_shared(conn, dest,
3969 SET_DENY_MODE(DENY_NONE) |
3970 SET_OPEN_MODE(DOS_OPEN_WRONLY), ofun,
3971 st.st_mode, 0, &Access, &action);
3973 if (!fsp2)
3975 close_file(fsp1, False);
3976 return (False);
3979 if ((ofun & 3) == 1)
3981 if (conn->vfs_ops.lseek(fsp2->fd, 0, SEEK_END) == -1)
3983 DEBUG(0,
3984 ("copy_file: error - sys_lseek returned error %s\n",
3985 strerror(errno)));
3987 * Stop the copy from occurring.
3989 ret = -1;
3990 st.st_size = 0;
3994 if (st.st_size)
3995 ret =
3996 vfs_transfer_file(-1, fsp1, -1, fsp2, st.st_size,
3997 NULL, 0, 0);
3999 close_file(fsp1, False);
4001 * As we are opening fsp1 read-only we only expect
4002 * an error on close on fsp2 if we are out of space.
4003 * Thus we don't look at the error return from the
4004 * close of fsp1.
4006 *err_ret = close_file(fsp2, False);
4008 return (ret == (SMB_OFF_T) st.st_size);
4013 /****************************************************************************
4014 reply to a file copy.
4015 ****************************************************************************/
4016 int reply_copy(connection_struct * conn, char *inbuf, char *outbuf,
4017 int dum_size, int dum_buffsize)
4019 int outsize = 0;
4020 pstring name;
4021 pstring directory;
4022 pstring mask, newname;
4023 char *p;
4024 int count = 0;
4025 int error = ERRnoaccess;
4026 int err = 0;
4027 BOOL has_wild;
4028 BOOL exists = False;
4029 int tid2 = SVAL(inbuf, smb_vwv0);
4030 int ofun = SVAL(inbuf, smb_vwv1);
4031 int flags = SVAL(inbuf, smb_vwv2);
4032 BOOL target_is_directory = False;
4033 BOOL bad_path1 = False;
4034 BOOL bad_path2 = False;
4035 BOOL rc = True;
4037 *directory = *mask = 0;
4039 pstrcpy(name, smb_buf(inbuf));
4040 pstrcpy(newname, smb_buf(inbuf) + 1 + strlen(name));
4042 DEBUG(3, ("reply_copy : %s -> %s\n", name, newname));
4044 if (tid2 != conn->cnum)
4046 /* can't currently handle inter share copies XXXX */
4047 DEBUG(3, ("Rejecting inter-share copy\n"));
4048 return (ERROR(ERRSRV, ERRinvdevice));
4051 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
4052 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4054 rc = unix_convert(name, conn, 0, &bad_path1, NULL);
4055 unix_convert(newname, conn, 0, &bad_path2, NULL);
4057 target_is_directory = vfs_directory_exist(conn, False, NULL);
4059 if ((flags & 1) && target_is_directory)
4061 return (ERROR(ERRDOS, ERRbadfile));
4064 if ((flags & 2) && !target_is_directory)
4066 return (ERROR(ERRDOS, ERRbadpath));
4069 if ((flags & (1 << 5)) && vfs_directory_exist(conn, name, NULL))
4071 /* wants a tree copy! XXXX */
4072 DEBUG(3, ("Rejecting tree copy\n"));
4073 return (ERROR(ERRSRV, ERRerror));
4076 p = strrchr(name, '/');
4077 if (!p)
4079 pstrcpy(directory, "./");
4080 pstrcpy(mask, name);
4082 else
4084 *p = 0;
4085 pstrcpy(directory, name);
4086 pstrcpy(mask, p + 1);
4090 * We should only check the mangled cache
4091 * here if unix_convert failed. This means
4092 * that the path in 'mask' doesn't exist
4093 * on the file system and so we need to look
4094 * for a possible mangle. This patch from
4095 * Tine Smukavec <valentin.smukavec@hermes.si>.
4098 if (!rc && is_mangled(mask))
4099 check_mangled_cache(mask);
4101 has_wild = strchr(mask, '*') || strchr(mask, '?');
4103 if (!has_wild)
4105 pstrcat(directory, "/");
4106 pstrcat(directory, mask);
4107 if (resolve_wildcards(directory, newname) &&
4108 copy_file(directory, newname, conn, ofun,
4109 count, target_is_directory, &err))
4110 count++;
4111 if (!count && err)
4113 errno = err;
4114 return (UNIXERROR(ERRHRD, ERRgeneral));
4116 if (!count)
4117 exists = vfs_file_exist(conn, directory, NULL);
4119 else
4121 void *dirptr = NULL;
4122 char *dname;
4123 pstring destname;
4125 if (check_name(directory, conn))
4126 dirptr = OpenDir(conn, directory, True);
4128 if (dirptr)
4130 error = ERRbadfile;
4132 if (strequal(mask, "????????.???"))
4133 pstrcpy(mask, "*");
4135 while ((dname = ReadDirName(dirptr)))
4137 pstring fname;
4138 pstrcpy(fname, dname);
4140 if (!mask_match
4141 (fname, mask, case_sensitive, False))
4142 continue;
4144 error = ERRnoaccess;
4145 slprintf(fname, sizeof(fname) - 1, "%s/%s",
4146 directory, dname);
4147 pstrcpy(destname, newname);
4148 if (resolve_wildcards(fname, destname) &&
4149 copy_file(fname, destname, conn, ofun,
4150 count, target_is_directory,
4151 &err)) count++;
4152 DEBUG(3,
4153 ("reply_copy : doing copy on %s -> %s\n",
4154 fname, destname));
4156 CloseDir(dirptr);
4160 if (count == 0)
4162 if (err)
4164 /* Error on close... */
4165 errno = err;
4166 return (UNIXERROR(ERRHRD, ERRgeneral));
4169 if (exists)
4170 return (ERROR(ERRDOS, error));
4171 else
4173 if ((errno == ENOENT) && (bad_path1 || bad_path2))
4175 unix_ERR_class = ERRDOS;
4176 unix_ERR_code = ERRbadpath;
4178 return (UNIXERROR(ERRDOS, error));
4182 outsize = set_message(outbuf, 1, 0, True);
4183 SSVAL(outbuf, smb_vwv0, count);
4185 return (outsize);
4188 /****************************************************************************
4189 reply to a setdir
4190 ****************************************************************************/
4191 int reply_setdir(connection_struct * conn, char *inbuf, char *outbuf,
4192 int dum_size, int dum_buffsize)
4194 int snum;
4195 int outsize = 0;
4196 BOOL ok = False;
4197 pstring newdir;
4199 snum = SNUM(conn);
4200 if (!CAN_SETDIR(snum))
4201 return (ERROR(ERRDOS, ERRnoaccess));
4203 pstrcpy(newdir, smb_buf(inbuf) + 1);
4204 strlower(newdir);
4206 if (strlen(newdir) == 0)
4208 ok = True;
4210 else
4212 ok = vfs_directory_exist(conn, newdir, NULL);
4213 if (ok)
4215 string_set(&conn->connectpath, newdir);
4219 if (!ok)
4220 return (ERROR(ERRDOS, ERRbadpath));
4222 outsize = set_message(outbuf, 0, 0, True);
4223 CVAL(outbuf, smb_reh) = CVAL(inbuf, smb_reh);
4225 DEBUG(3, ("setdir %s\n", newdir));
4227 return (outsize);
4230 /****************************************************************************
4231 reply to a lockingX request
4232 ****************************************************************************/
4234 int reply_lockingX(connection_struct * conn, char *inbuf, char *outbuf,
4235 int length, int bufsize)
4237 files_struct *fsp = file_fsp(inbuf, smb_vwv2);
4238 unsigned char locktype = CVAL(inbuf, smb_vwv3);
4239 #if 0
4240 unsigned char oplocklevel = CVAL(inbuf, smb_vwv3 + 1);
4241 #endif
4242 uint16 num_ulocks = SVAL(inbuf, smb_vwv6);
4243 uint16 num_locks = SVAL(inbuf, smb_vwv7);
4244 SMB_BIG_UINT count = 0, offset = 0;
4245 int32 lock_timeout = IVAL(inbuf, smb_vwv4);
4246 int i;
4247 char *data;
4248 uint32 ecode = 0, dummy2;
4249 int eclass = 0, dummy1;
4250 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES);
4251 BOOL err;
4253 CHECK_FSP(fsp, conn);
4254 CHECK_ERROR(fsp);
4256 data = smb_buf(inbuf);
4258 /* Check if this is an oplock break on a file
4259 we have granted an oplock on.
4261 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
4263 DEBUG(5,
4264 ("reply_lockingX: oplock break reply from client for fnum = %d\n",
4265 fsp->fnum));
4268 * Make sure we have granted an exclusive or batch oplock on this file.
4271 if (!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
4273 DEBUG(0,
4274 ("reply_lockingX: Error : oplock break from client for fnum = %d and \
4275 no oplock granted on this file (%s).\n",
4276 fsp->fnum, fsp->fsp_name));
4278 /* if this is a pure oplock break request then don't send a reply */
4279 if (num_locks == 0 && num_ulocks == 0)
4280 return -1;
4281 else
4282 return ERROR(ERRDOS, ERRlock);
4285 if (remove_oplock(fsp) == False)
4287 DEBUG(0,
4288 ("reply_lockingX: error in removing oplock on file %s\n",
4289 fsp->fsp_name));
4292 /* if this is a pure oplock break request then don't send a reply */
4293 if (num_locks == 0 && num_ulocks == 0)
4295 /* Sanity check - ensure a pure oplock break is not a
4296 chained request. */
4297 if (CVAL(inbuf, smb_vwv0) != 0xff)
4298 DEBUG(0,
4299 ("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4300 (unsigned int)CVAL(inbuf, smb_vwv0)));
4301 return -1;
4305 /* Data now points at the beginning of the list
4306 of smb_unlkrng structs */
4307 for (i = 0; i < (int)num_ulocks; i++)
4309 count = get_lock_count(data, i, large_file_format);
4310 offset = get_lock_offset(data, i, large_file_format, &err);
4313 * There is no error code marked "stupid client bug".... :-).
4315 if (err)
4316 return ERROR(ERRDOS, ERRnoaccess);
4318 DEBUG(10,
4319 ("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n",
4320 (double)offset, (double)count, fsp->fsp_name));
4322 if (!do_unlock(fsp, conn, count, offset, &eclass, &ecode))
4323 return ERROR(eclass, ecode);
4326 /* Setup the timeout in seconds. */
4327 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout / 1000);
4329 /* Now do any requested locks */
4330 data += ((large_file_format ? 20 : 10) * num_ulocks);
4332 /* Data now points at the beginning of the list
4333 of smb_lkrng structs */
4335 for (i = 0; i < (int)num_locks; i++)
4337 count = get_lock_count(data, i, large_file_format);
4338 offset = get_lock_offset(data, i, large_file_format, &err);
4341 * There is no error code marked "stupid client bug".... :-).
4343 if (err)
4344 return ERROR(ERRDOS, ERRnoaccess);
4346 DEBUG(10,
4347 ("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n",
4348 (double)offset, (double)count, fsp->fsp_name));
4350 if (!do_lock
4351 (fsp, conn, count, offset,
4352 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &eclass,
4353 &ecode))
4355 if ((ecode == ERRlock) && (lock_timeout != 0)
4356 && lp_blocking_locks(SNUM(conn)))
4359 * A blocking lock was requested. Package up
4360 * this smb into a queued request and push it
4361 * onto the blocking lock queue.
4363 if (push_blocking_lock_request
4364 (inbuf, length, lock_timeout, i))
4365 return -1;
4367 break;
4371 /* If any of the above locks failed, then we must unlock
4372 all of the previous locks (X/Open spec). */
4373 if (i != num_locks && num_locks != 0)
4376 * Ensure we don't do a remove on the lock that just failed,
4377 * as under POSIX rules, if we have a lock already there, we
4378 * will delete it (and we shouldn't) .....
4380 for (i--; i >= 0; i--)
4382 count = get_lock_count(data, i, large_file_format);
4383 offset =
4384 get_lock_offset(data, i, large_file_format,
4385 &err);
4388 * There is no error code marked "stupid client bug".... :-).
4390 if (err)
4391 return ERROR(ERRDOS, ERRnoaccess);
4393 do_unlock(fsp, conn, count, offset, &dummy1, &dummy2);
4395 return ERROR(eclass, ecode);
4398 set_message(outbuf, 2, 0, True);
4400 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4401 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
4403 return chain_reply(inbuf, outbuf, length, bufsize);
4407 /****************************************************************************
4408 reply to a SMBreadbmpx (read block multiplex) request
4409 ****************************************************************************/
4410 int reply_readbmpx(connection_struct * conn, char *inbuf, char *outbuf,
4411 int length, int bufsize)
4413 ssize_t nread = -1;
4414 ssize_t total_read;
4415 char *data;
4416 SMB_OFF_T startpos;
4417 int outsize;
4418 size_t maxcount;
4419 int max_per_packet;
4420 size_t tcount;
4421 int pad;
4422 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
4424 /* this function doesn't seem to work - disable by default */
4425 if (!lp_readbmpx())
4426 return (ERROR(ERRSRV, ERRuseSTD));
4428 outsize = set_message(outbuf, 8, 0, True);
4430 CHECK_FSP(fsp, conn);
4431 CHECK_READ(fsp);
4432 CHECK_ERROR(fsp);
4434 startpos = IVAL(inbuf, smb_vwv1);
4435 maxcount = SVAL(inbuf, smb_vwv3);
4437 data = smb_buf(outbuf);
4438 pad = ((long)data) % 4;
4439 if (pad)
4440 pad = 4 - pad;
4441 data += pad;
4443 max_per_packet = bufsize - (outsize + pad);
4444 tcount = maxcount;
4445 total_read = 0;
4447 if (is_locked
4448 (fsp, conn, (SMB_BIG_UINT) maxcount, (SMB_BIG_UINT) startpos,
4449 READ_LOCK))
4450 return (ERROR(ERRDOS, ERRlock));
4454 size_t N = MIN(max_per_packet, tcount - total_read);
4456 nread = read_file(fsp, data, startpos, N);
4458 if (nread <= 0)
4459 nread = 0;
4461 if (nread < (ssize_t) N)
4462 tcount = total_read + nread;
4464 set_message(outbuf, 8, nread, False);
4465 SIVAL(outbuf, smb_vwv0, startpos);
4466 SSVAL(outbuf, smb_vwv2, tcount);
4467 SSVAL(outbuf, smb_vwv6, nread);
4468 SSVAL(outbuf, smb_vwv7, smb_offset(data, outbuf));
4470 send_smb(smbd_server_fd(), outbuf);
4472 total_read += nread;
4473 startpos += nread;
4475 while (total_read < (ssize_t) tcount);
4477 return (-1);
4480 /****************************************************************************
4481 reply to a SMBwritebmpx (write block multiplex primary) request
4482 ****************************************************************************/
4484 int reply_writebmpx(connection_struct * conn, char *inbuf, char *outbuf,
4485 int size, int dum_buffsize)
4487 size_t numtowrite;
4488 ssize_t nwritten = -1;
4489 int outsize = 0;
4490 SMB_OFF_T startpos;
4491 size_t tcount;
4492 BOOL write_through;
4493 int smb_doff;
4494 char *data;
4495 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
4497 CHECK_FSP(fsp, conn);
4498 CHECK_WRITE(fsp);
4499 CHECK_ERROR(fsp);
4501 tcount = SVAL(inbuf, smb_vwv1);
4502 startpos = IVAL(inbuf, smb_vwv3);
4503 write_through = BITSETW(inbuf + smb_vwv7, 0);
4504 numtowrite = SVAL(inbuf, smb_vwv10);
4505 smb_doff = SVAL(inbuf, smb_vwv11);
4507 data = smb_base(inbuf) + smb_doff;
4509 /* If this fails we need to send an SMBwriteC response,
4510 not an SMBwritebmpx - set this up now so we don't forget */
4511 CVAL(outbuf, smb_com) = SMBwritec;
4513 if (is_locked
4514 (fsp, conn, (SMB_BIG_UINT) tcount, (SMB_BIG_UINT) startpos,
4515 WRITE_LOCK))
4516 return (ERROR(ERRDOS, ERRlock));
4518 nwritten = write_file(fsp, data, startpos, numtowrite);
4520 if (lp_syncalways(SNUM(conn)) || write_through)
4521 conn->vfs_ops.fsync(fsp->fd);
4523 if (nwritten < (ssize_t) numtowrite)
4524 return (UNIXERROR(ERRHRD, ERRdiskfull));
4526 /* If the maximum to be written to this file
4527 is greater than what we just wrote then set
4528 up a secondary struct to be attached to this
4529 fd, we will use this to cache error messages etc. */
4530 if ((ssize_t) tcount > nwritten)
4532 write_bmpx_struct *wbms;
4533 if (fsp->wbmpx_ptr != NULL)
4534 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4535 else
4536 wbms =
4537 (write_bmpx_struct *)
4538 malloc(sizeof(write_bmpx_struct));
4539 if (!wbms)
4541 DEBUG(0, ("Out of memory in reply_readmpx\n"));
4542 return (ERROR(ERRSRV, ERRnoresource));
4544 wbms->wr_mode = write_through;
4545 wbms->wr_discard = False; /* No errors yet */
4546 wbms->wr_total_written = nwritten;
4547 wbms->wr_errclass = 0;
4548 wbms->wr_error = 0;
4549 fsp->wbmpx_ptr = wbms;
4552 /* We are returning successfully, set the message type back to
4553 SMBwritebmpx */
4554 CVAL(outbuf, smb_com) = SMBwriteBmpx;
4556 outsize = set_message(outbuf, 1, 0, True);
4558 SSVALS(outbuf, smb_vwv0, -1); /* We don't support smb_remaining */
4560 DEBUG(3, ("writebmpx fnum=%d num=%d wrote=%d\n",
4561 fsp->fnum, (int)numtowrite, (int)nwritten));
4563 if (write_through && tcount == nwritten)
4565 /* we need to send both a primary and a secondary response */
4566 smb_setlen(outbuf, outsize - 4);
4567 send_smb(smbd_server_fd(), outbuf);
4569 /* now the secondary */
4570 outsize = set_message(outbuf, 1, 0, True);
4571 CVAL(outbuf, smb_com) = SMBwritec;
4572 SSVAL(outbuf, smb_vwv0, nwritten);
4575 return (outsize);
4579 /****************************************************************************
4580 reply to a SMBwritebs (write block multiplex secondary) request
4581 ****************************************************************************/
4582 int reply_writebs(connection_struct * conn, char *inbuf, char *outbuf,
4583 int dum_size, int dum_buffsize)
4585 size_t numtowrite;
4586 ssize_t nwritten = -1;
4587 int outsize = 0;
4588 SMB_OFF_T startpos;
4589 size_t tcount;
4590 BOOL write_through;
4591 int smb_doff;
4592 char *data;
4593 write_bmpx_struct *wbms;
4594 BOOL send_response = False;
4595 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
4597 CHECK_FSP(fsp, conn);
4598 CHECK_WRITE(fsp);
4600 tcount = SVAL(inbuf, smb_vwv1);
4601 startpos = IVAL(inbuf, smb_vwv2);
4602 numtowrite = SVAL(inbuf, smb_vwv6);
4603 smb_doff = SVAL(inbuf, smb_vwv7);
4605 data = smb_base(inbuf) + smb_doff;
4607 /* We need to send an SMBwriteC response, not an SMBwritebs */
4608 CVAL(outbuf, smb_com) = SMBwritec;
4610 /* This fd should have an auxiliary struct attached,
4611 check that it does */
4612 wbms = fsp->wbmpx_ptr;
4613 if (!wbms)
4614 return (-1);
4616 /* If write through is set we can return errors, else we must
4617 cache them */
4618 write_through = wbms->wr_mode;
4620 /* Check for an earlier error */
4621 if (wbms->wr_discard)
4622 return -1; /* Just discard the packet */
4624 nwritten = write_file(fsp, data, startpos, numtowrite);
4626 if (lp_syncalways(SNUM(conn)) || write_through)
4627 conn->vfs_ops.fsync(fsp->fd);
4629 if (nwritten < (ssize_t) numtowrite)
4631 if (write_through)
4633 /* We are returning an error - we can delete the aux struct */
4634 if (wbms)
4635 free((char *)wbms);
4636 fsp->wbmpx_ptr = NULL;
4637 return (ERROR(ERRHRD, ERRdiskfull));
4639 return (CACHE_ERROR(wbms, ERRHRD, ERRdiskfull));
4642 /* Increment the total written, if this matches tcount
4643 we can discard the auxiliary struct (hurrah !) and return a writeC */
4644 wbms->wr_total_written += nwritten;
4645 if (wbms->wr_total_written >= tcount)
4647 if (write_through)
4649 outsize = set_message(outbuf, 1, 0, True);
4650 SSVAL(outbuf, smb_vwv0, wbms->wr_total_written);
4651 send_response = True;
4654 free((char *)wbms);
4655 fsp->wbmpx_ptr = NULL;
4658 if (send_response)
4659 return (outsize);
4661 return (-1);
4665 /****************************************************************************
4666 reply to a SMBsetattrE
4667 ****************************************************************************/
4669 int reply_setattrE(connection_struct * conn, char *inbuf, char *outbuf,
4670 int size, int dum_buffsize)
4672 struct utimbuf unix_times;
4673 int outsize = 0;
4674 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
4676 outsize = set_message(outbuf, 0, 0, True);
4678 CHECK_FSP(fsp, conn);
4679 CHECK_ERROR(fsp);
4681 /* Convert the DOS times into unix times. Ignore create
4682 time as UNIX can't set this.
4684 unix_times.actime = make_unix_date2(inbuf + smb_vwv3);
4685 unix_times.modtime = make_unix_date2(inbuf + smb_vwv5);
4688 * Patch from Ray Frush <frush@engr.colostate.edu>
4689 * Sometimes times are sent as zero - ignore them.
4692 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4694 /* Ignore request */
4695 if (DEBUGLVL(3))
4697 dbgtext("reply_setattrE fnum=%d ", fsp->fnum);
4698 dbgtext
4699 ("ignoring zero request - not setting timestamps of 0\n");
4701 return (outsize);
4703 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4705 /* set modify time = to access time if modify time was 0 */
4706 unix_times.modtime = unix_times.actime;
4709 /* Set the date on this file */
4710 if (file_utime(conn, fsp->fsp_name, &unix_times))
4711 return (ERROR(ERRDOS, ERRnoaccess));
4713 DEBUG(3, ("reply_setattrE fnum=%d actime=%d modtime=%d\n",
4714 fsp->fnum, (int)unix_times.actime,
4715 (int)unix_times.modtime));
4717 return (outsize);
4721 /****************************************************************************
4722 reply to a SMBgetattrE
4723 ****************************************************************************/
4725 int reply_getattrE(connection_struct * conn, char *inbuf, char *outbuf,
4726 int size, int dum_buffsize)
4728 SMB_STRUCT_STAT sbuf;
4729 int outsize = 0;
4730 int mode;
4731 files_struct *fsp = file_fsp(inbuf, smb_vwv0);
4733 outsize = set_message(outbuf, 11, 0, True);
4735 CHECK_FSP(fsp, conn);
4736 CHECK_ERROR(fsp);
4738 /* Do an fstat on this file */
4739 if (fsp->conn->vfs_ops.fstat(fsp->fd, &sbuf))
4740 return (UNIXERROR(ERRDOS, ERRnoaccess));
4742 mode = dos_mode(conn, fsp->fsp_name, &sbuf);
4744 /* Convert the times into dos times. Set create
4745 date to be last modify date as UNIX doesn't save
4746 this */
4747 put_dos_date2(outbuf, smb_vwv0,
4748 get_create_time(&sbuf,
4749 lp_fake_dir_create_times(SNUM(conn))));
4750 put_dos_date2(outbuf, smb_vwv2, sbuf.st_atime);
4751 put_dos_date2(outbuf, smb_vwv4, sbuf.st_mtime);
4752 if (mode & aDIR)
4754 SIVAL(outbuf, smb_vwv6, 0);
4755 SIVAL(outbuf, smb_vwv8, 0);
4757 else
4759 SIVAL(outbuf, smb_vwv6, (uint32)sbuf.st_size);
4760 SIVAL(outbuf, smb_vwv8, SMB_ROUNDUP(sbuf.st_size, 1024));
4762 SSVAL(outbuf, smb_vwv10, mode);
4764 DEBUG(3, ("reply_getattrE fnum=%d\n", fsp->fnum));
4766 return (outsize);