move to SAFE_FREE()
[Samba.git] / source3 / smbd / reply.c
blob8527ebbe3413310f9ea6ace96e5a15095b80e4dc
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Andrew Bartlett 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "includes.h"
30 /* look in server.c for some explanation of these variables */
31 extern int Protocol;
32 extern int DEBUGLEVEL;
33 extern int max_send;
34 extern int max_recv;
35 extern char magic_char;
36 extern BOOL case_sensitive;
37 extern BOOL case_preserve;
38 extern BOOL short_case_preserve;
39 extern userdom_struct current_user_info;
40 extern pstring global_myname;
41 extern int global_oplock_break;
42 uint32 global_client_caps = 0;
43 unsigned int smb_echo_count = 0;
45 extern fstring remote_machine;
47 /****************************************************************************
48 report a possible attack via the password buffer overflow bug
49 ****************************************************************************/
51 static void overflow_attack(int len)
53 if( DEBUGLVL( 0 ) ) {
54 dbgtext( "ERROR: Invalid password length %d.\n", len );
55 dbgtext( "Your machine may be under attack by someone " );
56 dbgtext( "attempting to exploit an old bug.\n" );
57 dbgtext( "Attack was from IP = %s.\n", client_addr() );
62 /****************************************************************************
63 reply to an special message
64 ****************************************************************************/
66 int reply_special(char *inbuf,char *outbuf)
68 int outsize = 4;
69 int msg_type = CVAL(inbuf,0);
70 int msg_flags = CVAL(inbuf,1);
71 pstring name1,name2;
73 extern fstring local_machine;
74 int len;
75 char name_type = 0;
77 *name1 = *name2 = 0;
79 memset(outbuf,'\0',smb_size);
81 smb_setlen(outbuf,0);
83 switch (msg_type) {
84 case 0x81: /* session request */
85 CVAL(outbuf,0) = 0x82;
86 CVAL(outbuf,3) = 0;
87 if (name_len(inbuf+4) > 50 ||
88 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
89 DEBUG(0,("Invalid name length in session request\n"));
90 return(0);
92 name_extract(inbuf,4,name1);
93 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
94 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
95 name1,name2));
97 fstrcpy(remote_machine,name2);
98 remote_machine[15] = 0;
99 trim_string(remote_machine," "," ");
100 strlower(remote_machine);
101 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
103 fstrcpy(local_machine,name1);
104 len = strlen(local_machine);
105 if (len == 16) {
106 name_type = local_machine[15];
107 local_machine[15] = 0;
109 trim_string(local_machine," "," ");
110 strlower(local_machine);
111 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
113 DEBUG(2,("netbios connect: local=%s remote=%s\n",
114 local_machine, remote_machine ));
116 if (name_type == 'R') {
117 /* We are being asked for a pathworks session ---
118 no thanks! */
119 CVAL(outbuf, 0) = 0x83;
120 break;
123 /* only add the client's machine name to the list
124 of possibly valid usernames if we are operating
125 in share mode security */
126 if (lp_security() == SEC_SHARE) {
127 add_session_user(remote_machine);
130 reload_services(True);
131 reopen_logs();
133 claim_connection(NULL,"",MAXSTATUS,True);
135 break;
137 case 0x89: /* session keepalive request
138 (some old clients produce this?) */
139 CVAL(outbuf,0) = 0x85;
140 CVAL(outbuf,3) = 0;
141 break;
143 case 0x82: /* positive session response */
144 case 0x83: /* negative session response */
145 case 0x84: /* retarget session response */
146 DEBUG(0,("Unexpected session response\n"));
147 break;
149 case 0x85: /* session keepalive */
150 default:
151 return(0);
154 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
155 msg_type, msg_flags));
157 return(outsize);
161 /****************************************************************************
162 Reply to a tcon.
163 ****************************************************************************/
165 int reply_tcon(connection_struct *conn,
166 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
168 pstring service;
169 pstring password;
170 pstring dev;
171 int outsize = 0;
172 uint16 vuid = SVAL(inbuf,smb_uid);
173 int pwlen=0;
174 NTSTATUS ecode;
175 char *p;
177 START_PROFILE(SMBtcon);
179 *service = *password = *dev = 0;
181 p = smb_buf(inbuf)+1;
182 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
183 p += srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
184 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
186 p = strrchr_m(service,'\\');
187 if (p) {
188 pstrcpy(service, p+1);
191 conn = make_connection(service,password,pwlen,dev,vuid,&ecode);
193 if (!conn) {
194 END_PROFILE(SMBtcon);
195 return ERROR_NT(ecode);
198 outsize = set_message(outbuf,2,0,True);
199 SSVAL(outbuf,smb_vwv0,max_recv);
200 SSVAL(outbuf,smb_vwv1,conn->cnum);
201 SSVAL(outbuf,smb_tid,conn->cnum);
203 DEBUG(3,("tcon service=%s cnum=%d\n",
204 service, conn->cnum));
206 END_PROFILE(SMBtcon);
207 return(outsize);
210 /****************************************************************************
211 Reply to a tcon and X.
212 ****************************************************************************/
214 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
216 fstring service;
217 pstring password;
218 pstring devicename;
219 NTSTATUS ecode;
220 uint16 vuid = SVAL(inbuf,smb_uid);
221 int passlen = SVAL(inbuf,smb_vwv3);
222 pstring path;
223 char *p, *q;
224 START_PROFILE(SMBtconX);
226 *service = *password = *devicename = 0;
228 /* we might have to close an old one */
229 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
230 close_cnum(conn,vuid);
233 if (passlen > MAX_PASS_LEN) {
234 overflow_attack(passlen);
235 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
238 memcpy(password,smb_buf(inbuf),passlen);
239 password[passlen]=0;
240 p = smb_buf(inbuf) + passlen;
241 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
243 if (passlen != 24) {
244 if (strequal(password," "))
245 *password = 0;
246 passlen = strlen(password);
251 * the service name can be either: \\server\share
252 * or share directly like on the DELL PowerVault 705
254 if (*path=='\\') {
255 q = strchr_m(path+2,'\\');
256 if (!q) {
257 END_PROFILE(SMBtconX);
258 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
260 fstrcpy(service,q+1);
262 else
263 fstrcpy(service,path);
265 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
267 DEBUG(4,("Got device type %s\n",devicename));
269 conn = make_connection(service,password,passlen,devicename,vuid,&ecode);
271 if (!conn) {
272 END_PROFILE(SMBtconX);
273 return ERROR_NT(ecode);
276 if (Protocol < PROTOCOL_NT1) {
277 set_message(outbuf,2,0,True);
278 p = smb_buf(outbuf);
279 p += srvstr_push(outbuf, p, devicename, -1,
280 STR_TERMINATE|STR_ASCII);
281 set_message_end(outbuf,p);
282 } else {
283 /* NT sets the fstype of IPC$ to the null string */
284 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
286 set_message(outbuf,3,0,True);
288 p = smb_buf(outbuf);
289 p += srvstr_push(outbuf, p, devicename, -1,
290 STR_TERMINATE|STR_ASCII);
291 p += srvstr_push(outbuf, p, fsname, -1,
292 STR_TERMINATE);
294 set_message_end(outbuf,p);
296 /* what does setting this bit do? It is set by NT4 and
297 may affect the ability to autorun mounted cdroms */
298 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
300 init_dfsroot(conn, inbuf, outbuf);
304 DEBUG(3,("tconX service=%s \n",
305 service));
307 /* set the incoming and outgoing tid to the just created one */
308 SSVAL(inbuf,smb_tid,conn->cnum);
309 SSVAL(outbuf,smb_tid,conn->cnum);
311 END_PROFILE(SMBtconX);
312 return chain_reply(inbuf,outbuf,length,bufsize);
316 /****************************************************************************
317 reply to an unknown type
318 ****************************************************************************/
319 int reply_unknown(char *inbuf,char *outbuf)
321 int type;
322 type = CVAL(inbuf,smb_com);
324 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
325 smb_fn_name(type), type, type));
327 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
331 /****************************************************************************
332 reply to an ioctl
333 ****************************************************************************/
334 int reply_ioctl(connection_struct *conn,
335 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
337 uint16 device = SVAL(inbuf,smb_vwv1);
338 uint16 function = SVAL(inbuf,smb_vwv2);
339 uint32 ioctl_code = (device << 16) + function;
340 int replysize, outsize;
341 char *p;
342 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
343 START_PROFILE(SMBioctl);
345 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
347 switch (ioctl_code)
349 case IOCTL_QUERY_JOB_INFO:
350 replysize = 32;
351 break;
352 default:
353 END_PROFILE(SMBioctl);
354 return(ERROR_DOS(ERRSRV,ERRnosupport));
357 outsize = set_message(outbuf,8,replysize+1,True);
358 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
359 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
360 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
361 p = smb_buf(outbuf) + 1; /* Allow for alignment */
363 switch (ioctl_code)
365 case IOCTL_QUERY_JOB_INFO:
366 SSVAL(p,0,fsp->print_jobid); /* Job number */
367 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
368 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
369 break;
372 END_PROFILE(SMBioctl);
373 return outsize;
376 /****************************************************************************
377 This function breaks the authentication split. It needs sorting out.
378 I can't see why we can't hadle this INSIDE the check_password, as in then
379 end all it does it spit out an nt_status code.
380 ****************************************************************************/
381 /****************************************************************************
382 always return an error: it's just a matter of which one...
383 ****************************************************************************/
384 static int session_trust_account(connection_struct *conn, char *inbuf, char *outbuf, char *user,
385 char *smb_passwd, int smb_passlen,
386 char *smb_nt_passwd, int smb_nt_passlen)
388 /* check if trust account exists */
389 SAM_ACCOUNT *sam_trust_acct = NULL;
390 uint16 acct_ctrl;
391 BOOL ret;
392 auth_usersupplied_info user_info;
393 auth_serversupplied_info server_info;
394 AUTH_STR domain, smb_username, wksta_name;
396 ZERO_STRUCT(user_info);
397 ZERO_STRUCT(server_info);
398 ZERO_STRUCT(domain);
399 ZERO_STRUCT(smb_username);
400 ZERO_STRUCT(wksta_name);
402 domain.str = lp_workgroup();
403 domain.len = strlen(domain.str);
405 user_info.requested_domain = domain;
406 user_info.domain = domain;
408 smb_username.str = user;
409 smb_username.len = strlen(smb_username.str);
411 user_info.unix_username = smb_username; /* For the time-being */
412 user_info.smb_username = smb_username;
414 user_info.wksta_name = wksta_name;
416 user_info.lm_resp.buffer = (uint8 *)smb_passwd;
417 user_info.lm_resp.len = smb_passlen;
418 user_info.nt_resp.buffer = (uint8 *)smb_nt_passwd;
419 user_info.nt_resp.len = smb_nt_passlen;
421 if (!last_challenge(user_info.chal)) {
422 DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
423 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
426 pdb_init_sam(&sam_trust_acct);
428 if (lp_security() == SEC_USER) {
429 ret = pdb_getsampwnam(sam_trust_acct, user);
430 } else {
431 DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
432 pdb_free_sam(sam_trust_acct);
433 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
436 if (ret == False) {
437 /* lkclXXXX: workstation entry doesn't exist */
438 DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
439 pdb_free_sam(sam_trust_acct);
440 return(ERROR_NT(NT_STATUS_NO_SUCH_USER));
441 } else {
442 if ((smb_passlen != 24) || (smb_nt_passlen != 24)) {
443 DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
444 pdb_free_sam(sam_trust_acct);
445 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
448 if (!NT_STATUS_IS_OK(smb_password_ok(sam_trust_acct, &user_info, &server_info))) {
449 DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
450 pdb_free_sam(sam_trust_acct);
451 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
454 acct_ctrl = pdb_get_acct_ctrl(sam_trust_acct);
455 pdb_free_sam(sam_trust_acct);
456 if (acct_ctrl & ACB_DOMTRUST) {
457 DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
458 return(ERROR_NT(NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
461 if (acct_ctrl & ACB_SVRTRUST) {
462 DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
463 return(ERROR_NT(NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
466 if (acct_ctrl & ACB_WSTRUST) {
467 DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
468 return(ERROR_NT(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
472 /* don't know what to do: indicate logon failure */
473 return(ERROR_NT(NT_STATUS_LOGON_FAILURE));
477 /****************************************************************************
478 reply to a session setup command
479 ****************************************************************************/
481 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
483 int sess_vuid;
484 gid_t gid;
485 uid_t uid;
486 char* full_name;
487 int smb_bufsize;
488 int smb_apasslen = 0;
489 pstring smb_apasswd;
490 int smb_ntpasslen = 0;
491 pstring smb_ntpasswd;
492 pstring user;
493 pstring orig_user;
494 fstring domain;
495 fstring native_os;
496 fstring native_lanman;
497 BOOL guest=False;
498 static BOOL done_sesssetup = False;
499 BOOL doencrypt = SMBENCRYPT();
500 START_PROFILE(SMBsesssetupX);
502 *smb_apasswd = 0;
503 *smb_ntpasswd = 0;
505 smb_bufsize = SVAL(inbuf,smb_vwv2);
507 if (Protocol < PROTOCOL_NT1) {
508 smb_apasslen = SVAL(inbuf,smb_vwv7);
509 if (smb_apasslen > MAX_PASS_LEN) {
510 overflow_attack(smb_apasslen);
511 return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
514 memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
515 srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
517 if (!doencrypt && (lp_security() != SEC_SERVER)) {
518 smb_apasslen = strlen(smb_apasswd);
520 } else {
521 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
522 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
523 enum remote_arch_types ra_type = get_remote_arch();
524 char *p = smb_buf(inbuf);
526 if(global_client_caps == 0)
527 global_client_caps = IVAL(inbuf,smb_vwv11);
529 /* client_caps is used as final determination if client is NT or Win95.
530 This is needed to return the correct error codes in some
531 circumstances.
534 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
535 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
536 set_remote_arch( RA_WIN95);
540 if (passlen1 != 24 && passlen2 < 24)
541 doencrypt = False;
543 if (passlen1 > MAX_PASS_LEN) {
544 overflow_attack(passlen1);
545 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
548 passlen1 = MIN(passlen1, MAX_PASS_LEN);
549 passlen2 = MIN(passlen2, MAX_PASS_LEN);
551 if (!doencrypt) {
552 /* both Win95 and WinNT stuff up the password lengths for
553 non-encrypting systems. Uggh.
555 if passlen1==24 its a win95 system, and its setting the
556 password length incorrectly. Luckily it still works with the
557 default code because Win95 will null terminate the password
558 anyway
560 if passlen1>0 and passlen2>0 then maybe its a NT box and its
561 setting passlen2 to some random value which really stuffs
562 things up. we need to fix that one. */
564 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
565 passlen2 = 0;
568 if (lp_restrict_anonymous()) {
569 /* there seems to be no reason behind the differences in MS clients formatting
570 * various info like the domain, NativeOS, and NativeLanMan fields. Win95
571 * in particular seems to have an extra null byte between the username and the
572 * domain, or the password length calculation is wrong, which throws off the
573 * string extraction routines below. This makes the value of domain be the
574 * empty string, which fails the restrict anonymous check further down.
575 * This compensates for that, and allows browsing to work in mixed NT and
576 * win95 environments even when restrict anonymous is true. AAB
578 dump_data(100, p, 0x70);
579 DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
580 if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
581 DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
582 DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
583 DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
584 passlen1 = 1;
588 if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
589 /* Save the lanman2 password and the NT md4 password. */
590 smb_apasslen = passlen1;
591 memcpy(smb_apasswd,p,smb_apasslen);
592 smb_apasswd[smb_apasslen] = 0;
593 smb_ntpasslen = passlen2;
594 memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
595 smb_ntpasswd[smb_ntpasslen] = 0;
596 } else {
597 /* we use the first password that they gave */
598 smb_apasslen = passlen1;
599 StrnCpy(smb_apasswd,p,smb_apasslen);
601 /* trim the password */
602 smb_apasslen = strlen(smb_apasswd);
604 /* wfwg sometimes uses a space instead of a null */
605 if (strequal(smb_apasswd," ")) {
606 smb_apasslen = 0;
607 *smb_apasswd = 0;
611 p += passlen1 + passlen2;
612 p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
613 STR_TERMINATE);
615 * Incoming user and domain are in DOS codepage format. Convert
616 * to UNIX.
618 p += srvstr_pull(inbuf, domain, p, sizeof(domain),
619 -1, STR_TERMINATE);
620 p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
621 -1, STR_TERMINATE);
622 p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
623 -1, STR_TERMINATE);
624 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
625 domain,native_os,native_lanman));
628 /* don't allow for weird usernames or domains */
629 alpha_strcpy(user, user, ". _-$", sizeof(user));
630 alpha_strcpy(domain, domain, ". _-", sizeof(domain));
631 if (strstr(user, "..") || strstr(domain,"..")) {
632 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
635 if (lp_security() == SEC_SHARE) {
636 /* in share level we should ignore any passwords */
637 smb_ntpasslen = 0;
638 smb_apasslen = 0;
639 guest = True;
643 DEBUG(3,("sesssetupX:name=[%s]@[%s]\n",user, remote_machine));
645 /* If name ends in $ then I think it's asking about whether a */
646 /* computer with that name (minus the $) has access. For now */
647 /* say yes to everything ending in $. */
649 if (*user && (user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24)) {
650 END_PROFILE(SMBsesssetupX);
651 return session_trust_account(conn, inbuf, outbuf, user,
652 smb_apasswd, smb_apasslen,
653 smb_ntpasswd, smb_ntpasslen);
656 if (done_sesssetup && lp_restrict_anonymous()) {
657 /* tests show that even if browsing is done over already validated connections
658 * without a username and password the domain is still provided, which it
659 * wouldn't be if it was a purely anonymous connection. So, in order to
660 * restrict anonymous, we only deny connections that have no session
661 * information. If a domain has been provided, then it's not a purely
662 * anonymous connection. AAB
664 if (!*user && !*smb_apasswd && !*domain) {
665 DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
666 END_PROFILE(SMBsesssetupX);
667 return ERROR_DOS(ERRDOS,ERRnoaccess);
671 /* If no username is sent use the guest account */
672 if (!*user) {
673 pstrcpy(user,lp_guestaccount(-1));
674 guest = True;
677 pstrcpy(current_user_info.smb_name,user);
679 reload_services(True);
682 * Save the username before mapping. We will use
683 * the original username sent to us for security=server
684 * and security=domain checking.
687 pstrcpy( orig_user, user);
690 * Always try the "DOMAIN\user" lookup first, as this is the most
691 * specific case. If this fails then try the simple "user" lookup.
692 * But don't do this for guests, as this is always a local user.
695 if (!guest) {
696 pstring dom_user;
698 /* Work out who's who */
700 slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
701 domain, lp_winbind_separator(), user);
703 if (sys_getpwnam(dom_user) != NULL) {
704 pstrcpy(user, dom_user);
705 DEBUG(3,("Using unix username %s\n", dom_user));
709 * Pass the user through the NT -> unix user mapping
710 * function.
713 (void)map_username(user);
716 * Do any UNIX username case mangling.
718 smb_getpwnam(user, True);
721 add_session_user(user);
723 if (!guest) {
724 NTSTATUS nt_status;
725 nt_status = pass_check_smb(orig_user, user,
726 domain, remote_machine,
727 (unsigned char *)smb_apasswd,
728 smb_apasslen,
729 (unsigned char *)smb_ntpasswd,
730 smb_ntpasslen);
732 if NT_STATUS_IS_OK(nt_status) {
734 } else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)
735 && lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) {
736 DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
737 pstrcpy(user,lp_guestaccount(-1));
738 guest = True;
740 } else if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)
741 || NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER))
742 && (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
743 pstrcpy(user,lp_guestaccount(-1));
744 DEBUG(3,("Registered username %s for guest access\n",user));
745 guest = True;
747 } else {
748 return ERROR_NT(nt_status);
752 if (!strequal(user,lp_guestaccount(-1)) &&
753 lp_servicenumber(user) < 0)
755 add_home_service(user,get_user_home_dir(user));
759 /* it's ok - setup a reply */
760 if (Protocol < PROTOCOL_NT1) {
761 set_message(outbuf,3,0,True);
762 } else {
763 char *p;
764 set_message(outbuf,3,0,True);
765 p = smb_buf(outbuf);
766 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
767 p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
768 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
769 set_message_end(outbuf,p);
770 /* perhaps grab OS version here?? */
773 /* Set the correct uid in the outgoing and incoming packets
774 We will use this on future requests to determine which
775 user we should become.
778 const struct passwd *pw = smb_getpwnam(user,False);
779 if (!pw) {
780 DEBUG(1,("Username %s is invalid on this system\n",user));
781 END_PROFILE(SMBsesssetupX);
782 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
784 gid = pw->pw_gid;
785 uid = pw->pw_uid;
786 full_name = pw->pw_gecos;
789 if (guest)
790 SSVAL(outbuf,smb_vwv2,1);
792 /* register the name and uid as being validated, so further connections
793 to a uid can get through without a password, on the same VC */
795 sess_vuid = register_vuid(uid,gid,user,current_user_info.smb_name,domain,guest, full_name);
797 if (sess_vuid == -1) {
798 return ERROR_DOS(ERRDOS,ERRnoaccess);
802 SSVAL(outbuf,smb_uid,sess_vuid);
803 SSVAL(inbuf,smb_uid,sess_vuid);
805 if (!done_sesssetup)
806 max_send = MIN(max_send,smb_bufsize);
808 DEBUG(6,("Client requested max send size of %d\n", max_send));
810 done_sesssetup = True;
812 END_PROFILE(SMBsesssetupX);
813 return chain_reply(inbuf,outbuf,length,bufsize);
816 /****************************************************************************
817 reply to a chkpth
818 ****************************************************************************/
819 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
821 int outsize = 0;
822 int mode;
823 pstring name;
824 BOOL ok = False;
825 BOOL bad_path = False;
826 SMB_STRUCT_STAT sbuf;
827 START_PROFILE(SMBchkpth);
829 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
831 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
833 unix_convert(name,conn,0,&bad_path,&sbuf);
835 mode = SVAL(inbuf,smb_vwv0);
837 if (check_name(name,conn)) {
838 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
839 ok = S_ISDIR(sbuf.st_mode);
842 if (!ok) {
843 /* We special case this - as when a Windows machine
844 is parsing a path is steps through the components
845 one at a time - if a component fails it expects
846 ERRbadpath, not ERRbadfile.
848 if(errno == ENOENT) {
849 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
852 return(UNIXERROR(ERRDOS,ERRbadpath));
855 outsize = set_message(outbuf,0,0,True);
857 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
859 END_PROFILE(SMBchkpth);
860 return(outsize);
864 /****************************************************************************
865 reply to a getatr
866 ****************************************************************************/
867 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
869 pstring fname;
870 int outsize = 0;
871 SMB_STRUCT_STAT sbuf;
872 BOOL ok = False;
873 int mode=0;
874 SMB_OFF_T size=0;
875 time_t mtime=0;
876 BOOL bad_path = False;
877 char *p;
878 START_PROFILE(SMBgetatr);
880 p = smb_buf(inbuf) + 1;
881 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
883 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
885 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
886 under WfWg - weird! */
887 if (! (*fname))
889 mode = aHIDDEN | aDIR;
890 if (!CAN_WRITE(conn)) mode |= aRONLY;
891 size = 0;
892 mtime = 0;
893 ok = True;
895 else
897 unix_convert(fname,conn,0,&bad_path,&sbuf);
898 if (check_name(fname,conn))
900 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
902 mode = dos_mode(conn,fname,&sbuf);
903 size = sbuf.st_size;
904 mtime = sbuf.st_mtime;
905 if (mode & aDIR)
906 size = 0;
907 ok = True;
909 else
910 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
914 if (!ok)
916 if((errno == ENOENT) && bad_path)
918 unix_ERR_class = ERRDOS;
919 unix_ERR_code = ERRbadpath;
922 END_PROFILE(SMBgetatr);
923 return(UNIXERROR(ERRDOS,ERRbadfile));
926 outsize = set_message(outbuf,10,0,True);
928 SSVAL(outbuf,smb_vwv0,mode);
929 if(lp_dos_filetime_resolution(SNUM(conn)) )
930 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
931 else
932 put_dos_date3(outbuf,smb_vwv1,mtime);
933 SIVAL(outbuf,smb_vwv3,(uint32)size);
935 if (Protocol >= PROTOCOL_NT1) {
936 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
939 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
941 END_PROFILE(SMBgetatr);
942 return(outsize);
946 /****************************************************************************
947 reply to a setatr
948 ****************************************************************************/
949 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
951 pstring fname;
952 int outsize = 0;
953 BOOL ok=False;
954 int mode;
955 time_t mtime;
956 SMB_STRUCT_STAT sbuf;
957 BOOL bad_path = False;
958 char *p;
960 START_PROFILE(SMBsetatr);
962 p = smb_buf(inbuf) + 1;
963 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
964 unix_convert(fname,conn,0,&bad_path,&sbuf);
966 mode = SVAL(inbuf,smb_vwv0);
967 mtime = make_unix_date3(inbuf+smb_vwv1);
969 if (VALID_STAT_OF_DIR(sbuf))
970 mode |= aDIR;
971 if (check_name(fname,conn))
972 ok = (file_chmod(conn,fname,mode,NULL) == 0);
973 if (ok)
974 ok = set_filetime(conn,fname,mtime);
976 if (!ok)
978 if((errno == ENOENT) && bad_path)
980 unix_ERR_class = ERRDOS;
981 unix_ERR_code = ERRbadpath;
984 END_PROFILE(SMBsetatr);
985 return(UNIXERROR(ERRDOS,ERRnoaccess));
988 outsize = set_message(outbuf,0,0,True);
990 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
992 END_PROFILE(SMBsetatr);
993 return(outsize);
997 /****************************************************************************
998 reply to a dskattr
999 ****************************************************************************/
1000 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1002 int outsize = 0;
1003 SMB_BIG_UINT dfree,dsize,bsize;
1004 START_PROFILE(SMBdskattr);
1006 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
1008 outsize = set_message(outbuf,5,0,True);
1010 SSVAL(outbuf,smb_vwv0,dsize);
1011 SSVAL(outbuf,smb_vwv1,bsize/512);
1012 SSVAL(outbuf,smb_vwv2,512);
1013 SSVAL(outbuf,smb_vwv3,dfree);
1015 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1017 END_PROFILE(SMBdskattr);
1018 return(outsize);
1022 /****************************************************************************
1023 reply to a search
1024 Can be called from SMBsearch, SMBffirst or SMBfunique.
1025 ****************************************************************************/
1026 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1028 pstring mask;
1029 pstring directory;
1030 pstring fname;
1031 SMB_OFF_T size;
1032 int mode;
1033 time_t date;
1034 int dirtype;
1035 int outsize = 0;
1036 int numentries = 0;
1037 BOOL finished = False;
1038 int maxentries;
1039 int i;
1040 char *p;
1041 BOOL ok = False;
1042 int status_len;
1043 pstring path;
1044 char status[21];
1045 int dptr_num= -1;
1046 BOOL check_descend = False;
1047 BOOL expect_close = False;
1048 BOOL can_open = True;
1049 BOOL bad_path = False;
1050 START_PROFILE(SMBsearch);
1052 *mask = *directory = *fname = 0;
1054 /* If we were called as SMBffirst then we must expect close. */
1055 if(CVAL(inbuf,smb_com) == SMBffirst)
1056 expect_close = True;
1058 outsize = set_message(outbuf,1,3,True);
1059 maxentries = SVAL(inbuf,smb_vwv0);
1060 dirtype = SVAL(inbuf,smb_vwv1);
1061 p = smb_buf(inbuf) + 1;
1062 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1063 p++;
1064 status_len = SVAL(p, 0);
1065 p += 2;
1067 /* dirtype &= ~aDIR; */
1069 if (status_len == 0)
1071 SMB_STRUCT_STAT sbuf;
1072 pstring dir2;
1074 pstrcpy(directory,path);
1075 pstrcpy(dir2,path);
1076 unix_convert(directory,conn,0,&bad_path,&sbuf);
1077 unix_format(dir2);
1079 if (!check_name(directory,conn))
1080 can_open = False;
1082 p = strrchr_m(dir2,'/');
1083 if (p == NULL)
1085 pstrcpy(mask,dir2);
1086 *dir2 = 0;
1088 else
1090 *p = 0;
1091 pstrcpy(mask,p+1);
1094 p = strrchr_m(directory,'/');
1095 if (!p)
1096 *directory = 0;
1097 else
1098 *p = 0;
1100 if (strlen(directory) == 0)
1101 pstrcpy(directory,"./");
1102 memset((char *)status,'\0',21);
1103 CVAL(status,0) = dirtype;
1105 else
1107 memcpy(status,p,21);
1108 dirtype = CVAL(status,0) & 0x1F;
1109 conn->dirptr = dptr_fetch(status+12,&dptr_num);
1110 if (!conn->dirptr)
1111 goto SearchEmpty;
1112 string_set(&conn->dirpath,dptr_path(dptr_num));
1113 fstrcpy(mask, dptr_wcard(dptr_num));
1116 if (can_open)
1118 p = smb_buf(outbuf) + 3;
1120 ok = True;
1122 if (status_len == 0)
1124 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
1125 if (dptr_num < 0)
1127 if(dptr_num == -2)
1129 if((errno == ENOENT) && bad_path)
1131 unix_ERR_class = ERRDOS;
1132 unix_ERR_code = ERRbadpath;
1134 END_PROFILE(SMBsearch);
1135 return (UNIXERROR(ERRDOS,ERRnofids));
1137 END_PROFILE(SMBsearch);
1138 return ERROR_DOS(ERRDOS,ERRnofids);
1140 dptr_set_wcard(dptr_num, strdup(mask));
1143 DEBUG(4,("dptr_num is %d\n",dptr_num));
1145 if (ok)
1147 if ((dirtype&0x1F) == aVOLID)
1149 memcpy(p,status,21);
1150 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
1151 dptr_fill(p+12,dptr_num);
1152 if (dptr_zero(p+12) && (status_len==0))
1153 numentries = 1;
1154 else
1155 numentries = 0;
1156 p += DIR_STRUCT_SIZE;
1158 else
1160 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1161 conn->dirpath,lp_dontdescend(SNUM(conn))));
1162 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
1163 check_descend = True;
1165 for (i=numentries;(i<maxentries) && !finished;i++)
1167 finished =
1168 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1169 if (!finished)
1171 memcpy(p,status,21);
1172 make_dir_struct(p,mask,fname,size,mode,date);
1173 dptr_fill(p+12,dptr_num);
1174 numentries++;
1176 p += DIR_STRUCT_SIZE;
1179 } /* if (ok ) */
1183 SearchEmpty:
1185 if (numentries == 0 || !ok)
1187 CVAL(outbuf,smb_rcls) = ERRDOS;
1188 SSVAL(outbuf,smb_err,ERRnofiles);
1189 dptr_close(&dptr_num);
1192 /* If we were called as SMBffirst with smb_search_id == NULL
1193 and no entries were found then return error and close dirptr
1194 (X/Open spec) */
1196 if(ok && expect_close && numentries == 0 && status_len == 0)
1198 CVAL(outbuf,smb_rcls) = ERRDOS;
1199 SSVAL(outbuf,smb_err,ERRnofiles);
1200 /* Also close the dptr - we know it's gone */
1201 dptr_close(&dptr_num);
1204 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1205 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
1206 dptr_close(&dptr_num);
1208 SSVAL(outbuf,smb_vwv0,numentries);
1209 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1210 CVAL(smb_buf(outbuf),0) = 5;
1211 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1213 if (Protocol >= PROTOCOL_NT1) {
1214 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
1217 outsize += DIR_STRUCT_SIZE*numentries;
1218 smb_setlen(outbuf,outsize - 4);
1220 if ((! *directory) && dptr_path(dptr_num))
1221 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1223 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
1224 smb_fn_name(CVAL(inbuf,smb_com)),
1225 mask, directory, dirtype, numentries, maxentries ) );
1227 END_PROFILE(SMBsearch);
1228 return(outsize);
1232 /****************************************************************************
1233 reply to a fclose (stop directory search)
1234 ****************************************************************************/
1235 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1237 int outsize = 0;
1238 int status_len;
1239 pstring path;
1240 char status[21];
1241 int dptr_num= -2;
1242 char *p;
1244 START_PROFILE(SMBfclose);
1246 outsize = set_message(outbuf,1,0,True);
1247 p = smb_buf(inbuf) + 1;
1248 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
1249 p++;
1250 status_len = SVAL(p,0);
1251 p += 2;
1253 if (status_len == 0) {
1254 END_PROFILE(SMBfclose);
1255 return ERROR_DOS(ERRSRV,ERRsrverror);
1258 memcpy(status,p,21);
1260 if(dptr_fetch(status+12,&dptr_num)) {
1261 /* Close the dptr - we know it's gone */
1262 dptr_close(&dptr_num);
1265 SSVAL(outbuf,smb_vwv0,0);
1267 DEBUG(3,("search close\n"));
1269 END_PROFILE(SMBfclose);
1270 return(outsize);
1274 /****************************************************************************
1275 reply to an open
1276 ****************************************************************************/
1278 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1280 pstring fname;
1281 int outsize = 0;
1282 int fmode=0;
1283 int share_mode;
1284 SMB_OFF_T size = 0;
1285 time_t mtime=0;
1286 mode_t unixmode;
1287 int rmode=0;
1288 SMB_STRUCT_STAT sbuf;
1289 BOOL bad_path = False;
1290 files_struct *fsp;
1291 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1292 START_PROFILE(SMBopen);
1294 share_mode = SVAL(inbuf,smb_vwv0);
1296 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1298 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1300 unix_convert(fname,conn,0,&bad_path,&sbuf);
1302 unixmode = unix_mode(conn,aARCH,fname);
1304 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1305 unixmode, oplock_request,&rmode,NULL);
1307 if (!fsp)
1309 if((errno == ENOENT) && bad_path)
1311 unix_ERR_class = ERRDOS;
1312 unix_ERR_code = ERRbadpath;
1314 END_PROFILE(SMBopen);
1315 return(UNIXERROR(ERRDOS,ERRnoaccess));
1318 size = sbuf.st_size;
1319 fmode = dos_mode(conn,fname,&sbuf);
1320 mtime = sbuf.st_mtime;
1322 if (fmode & aDIR) {
1323 DEBUG(3,("attempt to open a directory %s\n",fname));
1324 close_file(fsp,False);
1325 END_PROFILE(SMBopen);
1326 return ERROR_DOS(ERRDOS,ERRnoaccess);
1329 outsize = set_message(outbuf,7,0,True);
1330 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1331 SSVAL(outbuf,smb_vwv1,fmode);
1332 if(lp_dos_filetime_resolution(SNUM(conn)) )
1333 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1334 else
1335 put_dos_date3(outbuf,smb_vwv2,mtime);
1336 SIVAL(outbuf,smb_vwv4,(uint32)size);
1337 SSVAL(outbuf,smb_vwv6,rmode);
1339 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1340 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1343 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1344 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1345 END_PROFILE(SMBopen);
1346 return(outsize);
1350 /****************************************************************************
1351 reply to an open and X
1352 ****************************************************************************/
1353 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1355 pstring fname;
1356 int smb_mode = SVAL(inbuf,smb_vwv3);
1357 int smb_attr = SVAL(inbuf,smb_vwv5);
1358 /* Breakout the oplock request bits so we can set the
1359 reply bits separately. */
1360 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1361 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1362 BOOL oplock_request = ex_oplock_request | core_oplock_request;
1363 #if 0
1364 int open_flags = SVAL(inbuf,smb_vwv2);
1365 int smb_sattr = SVAL(inbuf,smb_vwv4);
1366 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1367 #endif
1368 int smb_ofun = SVAL(inbuf,smb_vwv8);
1369 mode_t unixmode;
1370 SMB_OFF_T size=0;
1371 int fmode=0,mtime=0,rmode=0;
1372 SMB_STRUCT_STAT sbuf;
1373 int smb_action = 0;
1374 BOOL bad_path = False;
1375 files_struct *fsp;
1376 START_PROFILE(SMBopenX);
1378 /* If it's an IPC, pass off the pipe handler. */
1379 if (IS_IPC(conn)) {
1380 if (lp_nt_pipe_support()) {
1381 END_PROFILE(SMBopenX);
1382 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1383 } else {
1384 END_PROFILE(SMBopenX);
1385 return ERROR_DOS(ERRSRV,ERRaccess);
1389 /* XXXX we need to handle passed times, sattr and flags */
1390 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
1392 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1394 unix_convert(fname,conn,0,&bad_path,&sbuf);
1396 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1398 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1399 oplock_request, &rmode,&smb_action);
1401 if (!fsp)
1403 if((errno == ENOENT) && bad_path)
1405 unix_ERR_class = ERRDOS;
1406 unix_ERR_code = ERRbadpath;
1408 END_PROFILE(SMBopenX);
1409 return(UNIXERROR(ERRDOS,ERRnoaccess));
1412 size = sbuf.st_size;
1413 fmode = dos_mode(conn,fname,&sbuf);
1414 mtime = sbuf.st_mtime;
1415 if (fmode & aDIR) {
1416 close_file(fsp,False);
1417 END_PROFILE(SMBopenX);
1418 return ERROR_DOS(ERRDOS,ERRnoaccess);
1421 /* If the caller set the extended oplock request bit
1422 and we granted one (by whatever means) - set the
1423 correct bit for extended oplock reply.
1426 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1427 smb_action |= EXTENDED_OPLOCK_GRANTED;
1430 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1431 smb_action |= EXTENDED_OPLOCK_GRANTED;
1434 /* If the caller set the core oplock request bit
1435 and we granted one (by whatever means) - set the
1436 correct bit for core oplock reply.
1439 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1440 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1443 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1444 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1447 set_message(outbuf,15,0,True);
1448 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1449 SSVAL(outbuf,smb_vwv3,fmode);
1450 if(lp_dos_filetime_resolution(SNUM(conn)) )
1451 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1452 else
1453 put_dos_date3(outbuf,smb_vwv4,mtime);
1454 SIVAL(outbuf,smb_vwv6,(uint32)size);
1455 SSVAL(outbuf,smb_vwv8,rmode);
1456 SSVAL(outbuf,smb_vwv11,smb_action);
1458 END_PROFILE(SMBopenX);
1459 return chain_reply(inbuf,outbuf,length,bufsize);
1463 /****************************************************************************
1464 reply to a SMBulogoffX
1465 ****************************************************************************/
1466 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1468 uint16 vuid = SVAL(inbuf,smb_uid);
1469 user_struct *vuser = get_valid_user_struct(vuid);
1470 START_PROFILE(SMBulogoffX);
1472 if(vuser == 0) {
1473 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1476 /* in user level security we are supposed to close any files
1477 open by this user */
1478 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1479 file_close_user(vuid);
1482 invalidate_vuid(vuid);
1484 set_message(outbuf,2,0,True);
1486 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1488 END_PROFILE(SMBulogoffX);
1489 return chain_reply(inbuf,outbuf,length,bufsize);
1493 /****************************************************************************
1494 reply to a mknew or a create
1495 ****************************************************************************/
1496 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1498 pstring fname;
1499 int com;
1500 int outsize = 0;
1501 int createmode;
1502 mode_t unixmode;
1503 int ofun = 0;
1504 BOOL bad_path = False;
1505 files_struct *fsp;
1506 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1507 SMB_STRUCT_STAT sbuf;
1508 START_PROFILE(SMBcreate);
1510 com = SVAL(inbuf,smb_com);
1512 createmode = SVAL(inbuf,smb_vwv0);
1513 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1515 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1517 unix_convert(fname,conn,0,&bad_path,&sbuf);
1519 if (createmode & aVOLID) {
1520 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1523 unixmode = unix_mode(conn,createmode,fname);
1525 if(com == SMBmknew)
1527 /* We should fail if file exists. */
1528 ofun = FILE_CREATE_IF_NOT_EXIST;
1530 else
1532 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1533 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1536 /* Open file in dos compatibility share mode. */
1537 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1538 ofun, unixmode, oplock_request, NULL, NULL);
1540 if (!fsp)
1542 if((errno == ENOENT) && bad_path)
1544 unix_ERR_class = ERRDOS;
1545 unix_ERR_code = ERRbadpath;
1547 END_PROFILE(SMBcreate);
1548 return(UNIXERROR(ERRDOS,ERRnoaccess));
1551 outsize = set_message(outbuf,1,0,True);
1552 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1554 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1555 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1558 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1559 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1561 DEBUG( 2, ( "new file %s\n", fname ) );
1562 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1563 fname, fsp->fd, createmode, (int)unixmode ) );
1565 END_PROFILE(SMBcreate);
1566 return(outsize);
1570 /****************************************************************************
1571 reply to a create temporary file
1572 ****************************************************************************/
1573 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1575 pstring fname;
1576 int outsize = 0;
1577 int createmode;
1578 mode_t unixmode;
1579 BOOL bad_path = False;
1580 files_struct *fsp;
1581 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1582 int tmpfd;
1583 SMB_STRUCT_STAT sbuf;
1584 char *p, *s;
1586 START_PROFILE(SMBctemp);
1588 createmode = SVAL(inbuf,smb_vwv0);
1589 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1590 pstrcat(fname,"\\TMXXXXXX");
1592 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1594 unix_convert(fname,conn,0,&bad_path,&sbuf);
1596 unixmode = unix_mode(conn,createmode,fname);
1598 tmpfd = smb_mkstemp(fname);
1599 if (tmpfd == -1) {
1600 END_PROFILE(SMBctemp);
1601 return(UNIXERROR(ERRDOS,ERRnoaccess));
1604 vfs_stat(conn,fname,&sbuf);
1606 /* Open file in dos compatibility share mode. */
1607 /* We should fail if file does not exist. */
1608 fsp = open_file_shared(conn,fname,&sbuf,
1609 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1610 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1611 unixmode, oplock_request, NULL, NULL);
1613 /* close fd from smb_mkstemp() */
1614 close(tmpfd);
1616 if (!fsp)
1618 if((errno == ENOENT) && bad_path)
1620 unix_ERR_class = ERRDOS;
1621 unix_ERR_code = ERRbadpath;
1623 END_PROFILE(SMBctemp);
1624 return(UNIXERROR(ERRDOS,ERRnoaccess));
1627 outsize = set_message(outbuf,1,0,True);
1628 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1630 /* the returned filename is relative to the directory */
1631 s = strrchr_m(fname, '/');
1632 if (!s) {
1633 s = fname;
1634 } else {
1635 s++;
1638 p = smb_buf(outbuf);
1639 SSVALS(p, 0, -1); /* what is this? not in spec */
1640 SSVAL(p, 2, strlen(s));
1641 p += 4;
1642 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1643 outsize = set_message_end(outbuf, p);
1645 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1646 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1649 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1650 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1652 DEBUG( 2, ( "created temp file %s\n", fname ) );
1653 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1654 fname, fsp->fd, createmode, (int)unixmode ) );
1656 END_PROFILE(SMBctemp);
1657 return(outsize);
1661 /*******************************************************************
1662 check if a user is allowed to delete a file
1663 ********************************************************************/
1664 static BOOL can_delete(char *fname,connection_struct *conn, int dirtype)
1666 SMB_STRUCT_STAT sbuf;
1667 int fmode;
1669 if (!CAN_WRITE(conn)) return(False);
1671 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
1672 fmode = dos_mode(conn,fname,&sbuf);
1673 if (fmode & aDIR) return(False);
1674 if (!lp_delete_readonly(SNUM(conn))) {
1675 if (fmode & aRONLY) return(False);
1677 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1678 return(False);
1679 if (!check_file_sharing(conn,fname,False)) return(False);
1680 return(True);
1683 /****************************************************************************
1684 The guts of the unlink command, split out so it may be called by the NT SMB
1685 code.
1686 ****************************************************************************/
1688 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1690 pstring directory;
1691 pstring mask;
1692 char *p;
1693 int count=0;
1694 NTSTATUS error = NT_STATUS_OK;
1695 BOOL has_wild;
1696 BOOL exists=False;
1697 BOOL bad_path = False;
1698 BOOL rc = True;
1699 SMB_STRUCT_STAT sbuf;
1701 *directory = *mask = 0;
1703 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1705 p = strrchr_m(name,'/');
1706 if (!p) {
1707 pstrcpy(directory,"./");
1708 pstrcpy(mask,name);
1709 } else {
1710 *p = 0;
1711 pstrcpy(directory,name);
1712 pstrcpy(mask,p+1);
1716 * We should only check the mangled cache
1717 * here if unix_convert failed. This means
1718 * that the path in 'mask' doesn't exist
1719 * on the file system and so we need to look
1720 * for a possible mangle. This patch from
1721 * Tine Smukavec <valentin.smukavec@hermes.si>.
1724 if (!rc && is_mangled(mask))
1725 check_mangled_cache( mask );
1727 has_wild = ms_has_wild(mask);
1729 if (!has_wild) {
1730 pstrcat(directory,"/");
1731 pstrcat(directory,mask);
1732 if (!can_delete(directory,conn,dirtype)) {
1733 return NT_STATUS_SHARING_VIOLATION;
1735 if (vfs_unlink(conn,directory) == 0) {
1736 count++;
1738 if (!count)
1739 exists = vfs_file_exist(conn,directory,&sbuf);
1740 } else {
1741 void *dirptr = NULL;
1742 char *dname;
1744 if (check_name(directory,conn))
1745 dirptr = OpenDir(conn, directory, True);
1747 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1748 the pattern matches against the long name, otherwise the short name
1749 We don't implement this yet XXXX
1752 if (dirptr) {
1753 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1755 if (strequal(mask,"????????.???"))
1756 pstrcpy(mask,"*");
1758 while ((dname = ReadDirName(dirptr))) {
1759 pstring fname;
1760 pstrcpy(fname,dname);
1762 if(!mask_match(fname, mask, case_sensitive)) continue;
1764 error = NT_STATUS_ACCESS_DENIED;
1765 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1766 if (!can_delete(fname,conn,dirtype)) continue;
1767 if (vfs_unlink(conn,fname) == 0) count++;
1768 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1770 CloseDir(dirptr);
1774 if (count == 0 && NT_STATUS_IS_OK(error)) {
1775 error = map_nt_error_from_unix(errno);
1778 return error;
1781 /****************************************************************************
1782 Reply to a unlink
1783 ****************************************************************************/
1785 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1786 int dum_buffsize)
1788 int outsize = 0;
1789 pstring name;
1790 int dirtype;
1791 NTSTATUS status;
1792 START_PROFILE(SMBunlink);
1794 dirtype = SVAL(inbuf,smb_vwv0);
1796 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1798 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1800 DEBUG(3,("reply_unlink : %s\n",name));
1802 status = unlink_internals(conn, dirtype, name);
1803 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1806 * Win2k needs a changenotify request response before it will
1807 * update after a rename..
1809 process_pending_change_notify_queue((time_t)0);
1811 outsize = set_message(outbuf,0,0,True);
1813 END_PROFILE(SMBunlink);
1814 return outsize;
1817 /****************************************************************************
1818 Fail for readbraw.
1819 ****************************************************************************/
1821 void fail_readraw(void)
1823 pstring errstr;
1824 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)\n",
1825 strerror(errno) );
1826 exit_server(errstr);
1829 /****************************************************************************
1830 Reply to a readbraw (core+ protocol).
1831 ****************************************************************************/
1833 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1835 size_t maxcount,mincount;
1836 size_t nread = 0;
1837 SMB_OFF_T startpos;
1838 char *header = outbuf;
1839 ssize_t ret=0;
1840 files_struct *fsp;
1841 START_PROFILE(SMBreadbraw);
1844 * Special check if an oplock break has been issued
1845 * and the readraw request croses on the wire, we must
1846 * return a zero length response here.
1849 if(global_oplock_break) {
1850 _smb_setlen(header,0);
1851 if (write_data(smbd_server_fd(),header,4) != 4)
1852 fail_readraw();
1853 DEBUG(5,("readbraw - oplock break finished\n"));
1854 END_PROFILE(SMBreadbraw);
1855 return -1;
1858 fsp = file_fsp(inbuf,smb_vwv0);
1860 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1862 * fsp could be NULL here so use the value from the packet. JRA.
1864 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1865 _smb_setlen(header,0);
1866 if (write_data(smbd_server_fd(),header,4) != 4)
1867 fail_readraw();
1868 END_PROFILE(SMBreadbraw);
1869 return(-1);
1872 CHECK_FSP(fsp,conn);
1874 flush_write_cache(fsp, READRAW_FLUSH);
1876 startpos = IVAL(inbuf,smb_vwv1);
1877 if(CVAL(inbuf,smb_wct) == 10) {
1879 * This is a large offset (64 bit) read.
1881 #ifdef LARGE_SMB_OFF_T
1883 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1885 #else /* !LARGE_SMB_OFF_T */
1888 * Ensure we haven't been sent a >32 bit offset.
1891 if(IVAL(inbuf,smb_vwv8) != 0) {
1892 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1893 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1894 _smb_setlen(header,0);
1895 if (write_data(smbd_server_fd(),header,4) != 4)
1896 fail_readraw();
1897 END_PROFILE(SMBreadbraw);
1898 return(-1);
1901 #endif /* LARGE_SMB_OFF_T */
1903 if(startpos < 0) {
1904 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1905 _smb_setlen(header,0);
1906 if (write_data(smbd_server_fd(),header,4) != 4)
1907 fail_readraw();
1908 END_PROFILE(SMBreadbraw);
1909 return(-1);
1912 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1913 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1915 /* ensure we don't overrun the packet size */
1916 maxcount = MIN(65535,maxcount);
1917 maxcount = MAX(mincount,maxcount);
1919 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1920 SMB_OFF_T size = fsp->size;
1921 SMB_OFF_T sizeneeded = startpos + maxcount;
1923 if (size < sizeneeded) {
1924 SMB_STRUCT_STAT st;
1925 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1926 size = st.st_size;
1927 if (!fsp->can_write)
1928 fsp->size = size;
1931 if (startpos >= size)
1932 nread = 0;
1933 else
1934 nread = MIN(maxcount,(size - startpos));
1937 if (nread < mincount)
1938 nread = 0;
1940 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1941 (int)maxcount, (int)mincount, (int)nread ) );
1943 if (nread > 0) {
1944 ret = read_file(fsp,header+4,startpos,nread);
1945 if (ret < mincount)
1946 ret = 0;
1949 _smb_setlen(header,ret);
1950 if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
1951 fail_readraw();
1953 DEBUG(5,("readbraw finished\n"));
1954 END_PROFILE(SMBreadbraw);
1955 return -1;
1958 /****************************************************************************
1959 reply to a lockread (core+ protocol)
1960 ****************************************************************************/
1961 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1963 ssize_t nread = -1;
1964 char *data;
1965 int outsize = 0;
1966 SMB_OFF_T startpos;
1967 size_t numtoread;
1968 NTSTATUS status;
1969 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1970 START_PROFILE(SMBlockread);
1972 CHECK_FSP(fsp,conn);
1973 CHECK_READ(fsp);
1975 release_level_2_oplocks_on_change(fsp);
1977 numtoread = SVAL(inbuf,smb_vwv1);
1978 startpos = IVAL(inbuf,smb_vwv2);
1980 outsize = set_message(outbuf,5,3,True);
1981 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1982 data = smb_buf(outbuf) + 3;
1985 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1986 * protocol request that predates the read/write lock concept.
1987 * Thus instead of asking for a read lock here we need to ask
1988 * for a write lock. JRA.
1991 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid),
1992 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1994 if (NT_STATUS_V(status)) {
1995 if (lp_blocking_locks(SNUM(conn))) {
1997 * A blocking lock was requested. Package up
1998 * this smb into a queued request and push it
1999 * onto the blocking lock queue.
2001 if(push_blocking_lock_request(inbuf, length, -1, 0))
2002 END_PROFILE(SMBlockread);
2003 return -1;
2005 END_PROFILE(SMBlockread);
2006 return ERROR_NT(status);
2009 nread = read_file(fsp,data,startpos,numtoread);
2011 if (nread < 0) {
2012 END_PROFILE(SMBlockread);
2013 return(UNIXERROR(ERRDOS,ERRnoaccess));
2016 outsize += nread;
2017 SSVAL(outbuf,smb_vwv0,nread);
2018 SSVAL(outbuf,smb_vwv5,nread+3);
2019 SSVAL(smb_buf(outbuf),1,nread);
2021 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2022 fsp->fnum, (int)numtoread, (int)nread));
2024 END_PROFILE(SMBlockread);
2025 return(outsize);
2029 /****************************************************************************
2030 reply to a read
2031 ****************************************************************************/
2033 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2035 size_t numtoread;
2036 ssize_t nread = 0;
2037 char *data;
2038 SMB_OFF_T startpos;
2039 int outsize = 0;
2040 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2041 START_PROFILE(SMBread);
2043 CHECK_FSP(fsp,conn);
2044 CHECK_READ(fsp);
2046 numtoread = SVAL(inbuf,smb_vwv1);
2047 startpos = IVAL(inbuf,smb_vwv2);
2050 outsize = set_message(outbuf,5,3,True);
2051 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2052 data = smb_buf(outbuf) + 3;
2054 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2055 END_PROFILE(SMBread);
2056 return ERROR_DOS(ERRDOS,ERRlock);
2059 if (numtoread > 0)
2060 nread = read_file(fsp,data,startpos,numtoread);
2062 if (nread < 0) {
2063 END_PROFILE(SMBread);
2064 return(UNIXERROR(ERRDOS,ERRnoaccess));
2067 outsize += nread;
2068 SSVAL(outbuf,smb_vwv0,nread);
2069 SSVAL(outbuf,smb_vwv5,nread+3);
2070 CVAL(smb_buf(outbuf),0) = 1;
2071 SSVAL(smb_buf(outbuf),1,nread);
2073 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2074 fsp->fnum, (int)numtoread, (int)nread ) );
2076 END_PROFILE(SMBread);
2077 return(outsize);
2081 /****************************************************************************
2082 reply to a read and X
2083 ****************************************************************************/
2084 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2086 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2087 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2088 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2089 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2090 ssize_t nread = -1;
2091 char *data;
2092 START_PROFILE(SMBreadX);
2094 /* If it's an IPC, pass off the pipe handler. */
2095 if (IS_IPC(conn)) {
2096 END_PROFILE(SMBreadX);
2097 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2100 CHECK_FSP(fsp,conn);
2101 CHECK_READ(fsp);
2103 set_message(outbuf,12,0,True);
2104 data = smb_buf(outbuf);
2106 if(CVAL(inbuf,smb_wct) == 12) {
2107 #ifdef LARGE_SMB_OFF_T
2109 * This is a large offset (64 bit) read.
2111 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2113 #else /* !LARGE_SMB_OFF_T */
2116 * Ensure we haven't been sent a >32 bit offset.
2119 if(IVAL(inbuf,smb_vwv10) != 0) {
2120 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
2121 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2122 END_PROFILE(SMBreadX);
2123 return ERROR_DOS(ERRDOS,ERRbadaccess);
2126 #endif /* LARGE_SMB_OFF_T */
2130 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2131 END_PROFILE(SMBreadX);
2132 return ERROR_DOS(ERRDOS,ERRlock);
2134 nread = read_file(fsp,data,startpos,smb_maxcnt);
2136 if (nread < 0) {
2137 END_PROFILE(SMBreadX);
2138 return(UNIXERROR(ERRDOS,ERRnoaccess));
2141 SSVAL(outbuf,smb_vwv5,nread);
2142 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2143 SSVAL(smb_buf(outbuf),-2,nread);
2145 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
2146 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
2148 END_PROFILE(SMBreadX);
2149 return chain_reply(inbuf,outbuf,length,bufsize);
2152 /****************************************************************************
2153 reply to a writebraw (core+ or LANMAN1.0 protocol)
2154 ****************************************************************************/
2156 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2158 ssize_t nwritten=0;
2159 ssize_t total_written=0;
2160 size_t numtowrite=0;
2161 size_t tcount;
2162 SMB_OFF_T startpos;
2163 char *data=NULL;
2164 BOOL write_through;
2165 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2166 int outsize = 0;
2167 START_PROFILE(SMBwritebraw);
2169 CHECK_FSP(fsp,conn);
2170 CHECK_WRITE(fsp);
2172 tcount = IVAL(inbuf,smb_vwv1);
2173 startpos = IVAL(inbuf,smb_vwv3);
2174 write_through = BITSETW(inbuf+smb_vwv7,0);
2176 /* We have to deal with slightly different formats depending
2177 on whether we are using the core+ or lanman1.0 protocol */
2179 if(Protocol <= PROTOCOL_COREPLUS) {
2180 numtowrite = SVAL(smb_buf(inbuf),-2);
2181 data = smb_buf(inbuf);
2182 } else {
2183 numtowrite = SVAL(inbuf,smb_vwv10);
2184 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2187 /* force the error type */
2188 CVAL(inbuf,smb_com) = SMBwritec;
2189 CVAL(outbuf,smb_com) = SMBwritec;
2191 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2192 END_PROFILE(SMBwritebraw);
2193 return(ERROR_DOS(ERRDOS,ERRlock));
2196 if (numtowrite>0)
2197 nwritten = write_file(fsp,data,startpos,numtowrite);
2199 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2200 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2202 if (nwritten < numtowrite) {
2203 END_PROFILE(SMBwritebraw);
2204 return(UNIXERROR(ERRHRD,ERRdiskfull));
2207 total_written = nwritten;
2209 /* Return a message to the redirector to tell it to send more bytes */
2210 CVAL(outbuf,smb_com) = SMBwritebraw;
2211 SSVALS(outbuf,smb_vwv0,-1);
2212 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2213 if (!send_smb(smbd_server_fd(),outbuf))
2214 exit_server("reply_writebraw: send_smb failed.\n");
2216 /* Now read the raw data into the buffer and write it */
2217 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2218 exit_server("secondary writebraw failed");
2221 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2222 numtowrite = smb_len(inbuf);
2224 /* Set up outbuf to return the correct return */
2225 outsize = set_message(outbuf,1,0,True);
2226 CVAL(outbuf,smb_com) = SMBwritec;
2227 SSVAL(outbuf,smb_vwv0,total_written);
2229 if (numtowrite != 0) {
2231 if (numtowrite > BUFFER_SIZE) {
2232 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2233 (unsigned int)numtowrite ));
2234 exit_server("secondary writebraw failed");
2237 if (tcount > nwritten+numtowrite) {
2238 DEBUG(3,("Client overestimated the write %d %d %d\n",
2239 (int)tcount,(int)nwritten,(int)numtowrite));
2242 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2243 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2244 strerror(errno) ));
2245 exit_server("secondary writebraw failed");
2248 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2250 if (nwritten < (ssize_t)numtowrite) {
2251 CVAL(outbuf,smb_rcls) = ERRHRD;
2252 SSVAL(outbuf,smb_err,ERRdiskfull);
2255 if (nwritten > 0)
2256 total_written += nwritten;
2259 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2260 sync_file(conn,fsp);
2262 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2263 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2265 /* we won't return a status if write through is not selected - this follows what WfWg does */
2266 END_PROFILE(SMBwritebraw);
2267 if (!write_through && total_written==tcount) {
2269 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2270 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2272 if (!send_keepalive(smbd_server_fd()))
2273 exit_server("reply_writebraw: send of keepalive failed");
2274 return(-1);
2277 return(outsize);
2280 /****************************************************************************
2281 reply to a writeunlock (core+)
2282 ****************************************************************************/
2284 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2285 int size, int dum_buffsize)
2287 ssize_t nwritten = -1;
2288 size_t numtowrite;
2289 SMB_OFF_T startpos;
2290 char *data;
2291 NTSTATUS status;
2292 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2293 int outsize = 0;
2294 START_PROFILE(SMBwriteunlock);
2296 CHECK_FSP(fsp,conn);
2297 CHECK_WRITE(fsp);
2299 numtowrite = SVAL(inbuf,smb_vwv1);
2300 startpos = IVAL(inbuf,smb_vwv2);
2301 data = smb_buf(inbuf) + 3;
2303 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2304 WRITE_LOCK,False)) {
2305 END_PROFILE(SMBwriteunlock);
2306 return ERROR_DOS(ERRDOS,ERRlock);
2309 /* The special X/Open SMB protocol handling of
2310 zero length writes is *NOT* done for
2311 this call */
2312 if(numtowrite == 0)
2313 nwritten = 0;
2314 else
2315 nwritten = write_file(fsp,data,startpos,numtowrite);
2317 if (lp_syncalways(SNUM(conn)))
2318 sync_file(conn,fsp);
2320 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2321 END_PROFILE(SMBwriteunlock);
2322 return(UNIXERROR(ERRDOS,ERRnoaccess));
2325 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2326 (SMB_BIG_UINT)startpos);
2327 if (NT_STATUS_V(status)) {
2328 END_PROFILE(SMBwriteunlock);
2329 return ERROR_NT(status);
2332 outsize = set_message(outbuf,1,0,True);
2334 SSVAL(outbuf,smb_vwv0,nwritten);
2336 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2337 fsp->fnum, (int)numtowrite, (int)nwritten));
2339 END_PROFILE(SMBwriteunlock);
2340 return outsize;
2344 /****************************************************************************
2345 Reply to a write.
2346 ****************************************************************************/
2348 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2350 size_t numtowrite;
2351 ssize_t nwritten = -1;
2352 SMB_OFF_T startpos;
2353 char *data;
2354 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2355 int outsize = 0;
2356 START_PROFILE(SMBwrite);
2358 /* If it's an IPC, pass off the pipe handler. */
2359 if (IS_IPC(conn)) {
2360 END_PROFILE(SMBwrite);
2361 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2364 CHECK_FSP(fsp,conn);
2365 CHECK_WRITE(fsp);
2367 numtowrite = SVAL(inbuf,smb_vwv1);
2368 startpos = IVAL(inbuf,smb_vwv2);
2369 data = smb_buf(inbuf) + 3;
2371 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2372 END_PROFILE(SMBwrite);
2373 return ERROR_DOS(ERRDOS,ERRlock);
2376 /* X/Open SMB protocol says that if smb_vwv1 is
2377 zero then the file size should be extended or
2378 truncated to the size given in smb_vwv[2-3] */
2379 if(numtowrite == 0) {
2380 /* This is actually an allocate call, not set EOF. JRA */
2381 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2382 if (nwritten < 0) {
2383 END_PROFILE(SMBwrite);
2384 return ERROR_NT(NT_STATUS_DISK_FULL);
2386 } else
2387 nwritten = write_file(fsp,data,startpos,numtowrite);
2389 if (lp_syncalways(SNUM(conn)))
2390 sync_file(conn,fsp);
2392 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2393 END_PROFILE(SMBwrite);
2394 return(UNIXERROR(ERRDOS,ERRnoaccess));
2397 outsize = set_message(outbuf,1,0,True);
2399 SSVAL(outbuf,smb_vwv0,nwritten);
2401 if (nwritten < (ssize_t)numtowrite) {
2402 CVAL(outbuf,smb_rcls) = ERRHRD;
2403 SSVAL(outbuf,smb_err,ERRdiskfull);
2406 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
2407 fsp->fnum, (int)numtowrite, (int)nwritten));
2409 END_PROFILE(SMBwrite);
2410 return(outsize);
2414 /****************************************************************************
2415 reply to a write and X
2416 ****************************************************************************/
2417 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2419 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2420 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2421 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2422 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2423 ssize_t nwritten = -1;
2424 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2425 unsigned int smblen = smb_len(inbuf);
2426 char *data;
2427 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2428 START_PROFILE(SMBwriteX);
2430 /* If it's an IPC, pass off the pipe handler. */
2431 if (IS_IPC(conn)) {
2432 END_PROFILE(SMBwriteX);
2433 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2436 CHECK_FSP(fsp,conn);
2437 CHECK_WRITE(fsp);
2439 /* Deal with possible LARGE_WRITEX */
2440 if (large_writeX)
2441 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2443 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2444 END_PROFILE(SMBwriteX);
2445 return ERROR_DOS(ERRDOS,ERRbadmem);
2448 data = smb_base(inbuf) + smb_doff;
2450 if(CVAL(inbuf,smb_wct) == 14) {
2451 #ifdef LARGE_SMB_OFF_T
2453 * This is a large offset (64 bit) write.
2455 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2457 #else /* !LARGE_SMB_OFF_T */
2460 * Ensure we haven't been sent a >32 bit offset.
2463 if(IVAL(inbuf,smb_vwv12) != 0) {
2464 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2465 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2466 END_PROFILE(SMBwriteX);
2467 return ERROR_DOS(ERRDOS,ERRbadaccess);
2470 #endif /* LARGE_SMB_OFF_T */
2473 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2474 END_PROFILE(SMBwriteX);
2475 return ERROR_DOS(ERRDOS,ERRlock);
2478 /* X/Open SMB protocol says that, unlike SMBwrite
2479 if the length is zero then NO truncation is
2480 done, just a write of zero. To truncate a file,
2481 use SMBwrite. */
2482 if(numtowrite == 0)
2483 nwritten = 0;
2484 else
2485 nwritten = write_file(fsp,data,startpos,numtowrite);
2487 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2488 END_PROFILE(SMBwriteX);
2489 return(UNIXERROR(ERRDOS,ERRnoaccess));
2492 set_message(outbuf,6,0,True);
2494 SSVAL(outbuf,smb_vwv2,nwritten);
2495 if (large_writeX)
2496 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2498 if (nwritten < (ssize_t)numtowrite) {
2499 CVAL(outbuf,smb_rcls) = ERRHRD;
2500 SSVAL(outbuf,smb_err,ERRdiskfull);
2503 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2504 fsp->fnum, (int)numtowrite, (int)nwritten));
2506 if (lp_syncalways(SNUM(conn)) || write_through)
2507 sync_file(conn,fsp);
2509 END_PROFILE(SMBwriteX);
2510 return chain_reply(inbuf,outbuf,length,bufsize);
2514 /****************************************************************************
2515 reply to a lseek
2516 ****************************************************************************/
2518 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2520 SMB_OFF_T startpos;
2521 SMB_OFF_T res= -1;
2522 int mode,umode;
2523 int outsize = 0;
2524 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2525 START_PROFILE(SMBlseek);
2527 CHECK_FSP(fsp,conn);
2529 flush_write_cache(fsp, SEEK_FLUSH);
2531 mode = SVAL(inbuf,smb_vwv1) & 3;
2532 startpos = IVALS(inbuf,smb_vwv2);
2534 switch (mode) {
2535 case 0: umode = SEEK_SET; break;
2536 case 1: umode = SEEK_CUR; break;
2537 case 2: umode = SEEK_END; break;
2538 default:
2539 umode = SEEK_SET; break;
2542 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2544 * Check for the special case where a seek before the start
2545 * of the file sets the offset to zero. Added in the CIFS spec,
2546 * section 4.2.7.
2549 if(errno == EINVAL) {
2550 SMB_OFF_T current_pos = startpos;
2552 if(umode == SEEK_CUR) {
2554 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2555 END_PROFILE(SMBlseek);
2556 return(UNIXERROR(ERRDOS,ERRnoaccess));
2559 current_pos += startpos;
2561 } else if (umode == SEEK_END) {
2563 SMB_STRUCT_STAT sbuf;
2565 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2566 END_PROFILE(SMBlseek);
2567 return(UNIXERROR(ERRDOS,ERRnoaccess));
2570 current_pos += sbuf.st_size;
2573 if(current_pos < 0)
2574 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2577 if(res == -1) {
2578 END_PROFILE(SMBlseek);
2579 return(UNIXERROR(ERRDOS,ERRnoaccess));
2583 fsp->pos = res;
2585 outsize = set_message(outbuf,2,0,True);
2586 SIVAL(outbuf,smb_vwv0,res);
2588 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2589 fsp->fnum, (double)startpos, (double)res, mode));
2591 END_PROFILE(SMBlseek);
2592 return(outsize);
2595 /****************************************************************************
2596 reply to a flush
2597 ****************************************************************************/
2599 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2601 int outsize = set_message(outbuf,0,0,True);
2602 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2603 START_PROFILE(SMBflush);
2605 CHECK_FSP(fsp,conn);
2607 if (!fsp) {
2608 file_sync_all(conn);
2609 } else {
2610 sync_file(conn,fsp);
2613 DEBUG(3,("flush\n"));
2614 END_PROFILE(SMBflush);
2615 return(outsize);
2619 /****************************************************************************
2620 reply to a exit
2621 ****************************************************************************/
2622 int reply_exit(connection_struct *conn,
2623 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2625 int outsize;
2626 START_PROFILE(SMBexit);
2627 outsize = set_message(outbuf,0,0,True);
2629 DEBUG(3,("exit\n"));
2631 END_PROFILE(SMBexit);
2632 return(outsize);
2636 /****************************************************************************
2637 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2638 ****************************************************************************/
2639 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2640 int dum_buffsize)
2642 int outsize = 0;
2643 time_t mtime;
2644 int32 eclass = 0, err = 0;
2645 files_struct *fsp = NULL;
2646 START_PROFILE(SMBclose);
2648 outsize = set_message(outbuf,0,0,True);
2650 /* If it's an IPC, pass off to the pipe handler. */
2651 if (IS_IPC(conn)) {
2652 END_PROFILE(SMBclose);
2653 return reply_pipe_close(conn, inbuf,outbuf);
2656 fsp = file_fsp(inbuf,smb_vwv0);
2659 * We can only use CHECK_FSP if we know it's not a directory.
2662 if(!fsp || (fsp->conn != conn)) {
2663 END_PROFILE(SMBclose);
2664 return ERROR_DOS(ERRDOS,ERRbadfid);
2667 if(fsp->is_directory || fsp->stat_open) {
2669 * Special case - close NT SMB directory or stat file
2670 * handle.
2672 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2673 close_file(fsp,True);
2674 } else {
2676 * Close ordinary file.
2678 int close_err;
2681 * If there was a modify time outstanding,
2682 * try and set it here.
2684 if(fsp->pending_modtime)
2685 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2688 * Now take care of any time sent in the close.
2690 mtime = make_unix_date3(inbuf+smb_vwv1);
2692 /* try and set the date */
2693 set_filetime(conn, fsp->fsp_name,mtime);
2695 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2696 fsp->fd, fsp->fnum,
2697 conn->num_files_open));
2700 * close_file() returns the unix errno if an error
2701 * was detected on close - normally this is due to
2702 * a disk full error. If not then it was probably an I/O error.
2705 if((close_err = close_file(fsp,True)) != 0) {
2706 errno = close_err;
2707 END_PROFILE(SMBclose);
2708 return (UNIXERROR(ERRHRD,ERRgeneral));
2712 /* We have a cached error */
2713 if(eclass || err) {
2714 END_PROFILE(SMBclose);
2715 return ERROR_DOS(eclass,err);
2718 END_PROFILE(SMBclose);
2719 return(outsize);
2723 /****************************************************************************
2724 reply to a writeclose (Core+ protocol)
2725 ****************************************************************************/
2727 int reply_writeclose(connection_struct *conn,
2728 char *inbuf,char *outbuf, int size, int dum_buffsize)
2730 size_t numtowrite;
2731 ssize_t nwritten = -1;
2732 int outsize = 0;
2733 int close_err = 0;
2734 SMB_OFF_T startpos;
2735 char *data;
2736 time_t mtime;
2737 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2738 START_PROFILE(SMBwriteclose);
2740 CHECK_FSP(fsp,conn);
2741 CHECK_WRITE(fsp);
2743 numtowrite = SVAL(inbuf,smb_vwv1);
2744 startpos = IVAL(inbuf,smb_vwv2);
2745 mtime = make_unix_date3(inbuf+smb_vwv4);
2746 data = smb_buf(inbuf) + 1;
2748 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2749 END_PROFILE(SMBwriteclose);
2750 return ERROR_DOS(ERRDOS,ERRlock);
2753 nwritten = write_file(fsp,data,startpos,numtowrite);
2755 set_filetime(conn, fsp->fsp_name,mtime);
2757 close_err = close_file(fsp,True);
2759 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2760 fsp->fnum, (int)numtowrite, (int)nwritten,
2761 conn->num_files_open));
2763 if (nwritten <= 0) {
2764 END_PROFILE(SMBwriteclose);
2765 return(UNIXERROR(ERRDOS,ERRnoaccess));
2768 if(close_err != 0) {
2769 errno = close_err;
2770 END_PROFILE(SMBwriteclose);
2771 return(UNIXERROR(ERRHRD,ERRgeneral));
2774 outsize = set_message(outbuf,1,0,True);
2776 SSVAL(outbuf,smb_vwv0,nwritten);
2777 END_PROFILE(SMBwriteclose);
2778 return(outsize);
2782 /****************************************************************************
2783 reply to a lock
2784 ****************************************************************************/
2785 int reply_lock(connection_struct *conn,
2786 char *inbuf,char *outbuf, int length, int dum_buffsize)
2788 int outsize = set_message(outbuf,0,0,True);
2789 SMB_BIG_UINT count,offset;
2790 NTSTATUS status;
2791 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2792 START_PROFILE(SMBlock);
2794 CHECK_FSP(fsp,conn);
2796 release_level_2_oplocks_on_change(fsp);
2798 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2799 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2801 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2802 fsp->fd, fsp->fnum, (double)offset, (double)count));
2804 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2805 if (NT_STATUS_V(status)) {
2806 if (lp_blocking_locks(SNUM(conn))) {
2808 * A blocking lock was requested. Package up
2809 * this smb into a queued request and push it
2810 * onto the blocking lock queue.
2812 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2813 END_PROFILE(SMBlock);
2814 return -1;
2817 END_PROFILE(SMBlock);
2818 return ERROR_NT(status);
2821 END_PROFILE(SMBlock);
2822 return(outsize);
2826 /****************************************************************************
2827 reply to a unlock
2828 ****************************************************************************/
2829 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2830 int dum_buffsize)
2832 int outsize = set_message(outbuf,0,0,True);
2833 SMB_BIG_UINT count,offset;
2834 NTSTATUS status;
2835 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2836 START_PROFILE(SMBunlock);
2838 CHECK_FSP(fsp,conn);
2840 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2841 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2843 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2844 if (NT_STATUS_V(status)) {
2845 END_PROFILE(SMBunlock);
2846 return ERROR_NT(status);
2849 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2850 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2852 END_PROFILE(SMBunlock);
2853 return(outsize);
2857 /****************************************************************************
2858 reply to a tdis
2859 ****************************************************************************/
2860 int reply_tdis(connection_struct *conn,
2861 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2863 int outsize = set_message(outbuf,0,0,True);
2864 uint16 vuid;
2865 START_PROFILE(SMBtdis);
2867 vuid = SVAL(inbuf,smb_uid);
2869 if (!conn) {
2870 DEBUG(4,("Invalid connection in tdis\n"));
2871 END_PROFILE(SMBtdis);
2872 return ERROR_DOS(ERRSRV,ERRinvnid);
2875 conn->used = False;
2877 close_cnum(conn,vuid);
2879 END_PROFILE(SMBtdis);
2880 return outsize;
2885 /****************************************************************************
2886 reply to a echo
2887 ****************************************************************************/
2888 int reply_echo(connection_struct *conn,
2889 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2891 int smb_reverb = SVAL(inbuf,smb_vwv0);
2892 int seq_num;
2893 unsigned int data_len = smb_buflen(inbuf);
2894 int outsize = set_message(outbuf,1,data_len,True);
2895 START_PROFILE(SMBecho);
2897 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2899 /* copy any incoming data back out */
2900 if (data_len > 0)
2901 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2903 if (smb_reverb > 100) {
2904 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2905 smb_reverb = 100;
2908 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2909 SSVAL(outbuf,smb_vwv0,seq_num);
2911 smb_setlen(outbuf,outsize - 4);
2913 if (!send_smb(smbd_server_fd(),outbuf))
2914 exit_server("reply_echo: send_smb failed.\n");
2917 DEBUG(3,("echo %d times\n", smb_reverb));
2919 smb_echo_count++;
2921 END_PROFILE(SMBecho);
2922 return -1;
2926 /****************************************************************************
2927 reply to a printopen
2928 ****************************************************************************/
2929 int reply_printopen(connection_struct *conn,
2930 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2932 int outsize = 0;
2933 files_struct *fsp;
2934 START_PROFILE(SMBsplopen);
2936 if (!CAN_PRINT(conn)) {
2937 END_PROFILE(SMBsplopen);
2938 return ERROR_DOS(ERRDOS,ERRnoaccess);
2941 /* Open for exclusive use, write only. */
2942 fsp = print_fsp_open(conn);
2944 if (!fsp) {
2945 END_PROFILE(SMBsplopen);
2946 return(UNIXERROR(ERRDOS,ERRnoaccess));
2949 outsize = set_message(outbuf,1,0,True);
2950 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2952 DEBUG(3,("openprint fd=%d fnum=%d\n",
2953 fsp->fd, fsp->fnum));
2955 END_PROFILE(SMBsplopen);
2956 return(outsize);
2960 /****************************************************************************
2961 reply to a printclose
2962 ****************************************************************************/
2963 int reply_printclose(connection_struct *conn,
2964 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2966 int outsize = set_message(outbuf,0,0,True);
2967 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2968 int close_err = 0;
2969 START_PROFILE(SMBsplclose);
2971 CHECK_FSP(fsp,conn);
2973 if (!CAN_PRINT(conn)) {
2974 END_PROFILE(SMBsplclose);
2975 return ERROR_DOS(ERRDOS,ERRnoaccess);
2978 DEBUG(3,("printclose fd=%d fnum=%d\n",
2979 fsp->fd,fsp->fnum));
2981 close_err = close_file(fsp,True);
2983 if(close_err != 0) {
2984 errno = close_err;
2985 END_PROFILE(SMBsplclose);
2986 return(UNIXERROR(ERRHRD,ERRgeneral));
2989 END_PROFILE(SMBsplclose);
2990 return(outsize);
2994 /****************************************************************************
2995 reply to a printqueue
2996 ****************************************************************************/
2997 int reply_printqueue(connection_struct *conn,
2998 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3000 int outsize = set_message(outbuf,2,3,True);
3001 int max_count = SVAL(inbuf,smb_vwv0);
3002 int start_index = SVAL(inbuf,smb_vwv1);
3003 START_PROFILE(SMBsplretq);
3005 /* we used to allow the client to get the cnum wrong, but that
3006 is really quite gross and only worked when there was only
3007 one printer - I think we should now only accept it if they
3008 get it right (tridge) */
3009 if (!CAN_PRINT(conn)) {
3010 END_PROFILE(SMBsplretq);
3011 return ERROR_DOS(ERRDOS,ERRnoaccess);
3014 SSVAL(outbuf,smb_vwv0,0);
3015 SSVAL(outbuf,smb_vwv1,0);
3016 CVAL(smb_buf(outbuf),0) = 1;
3017 SSVAL(smb_buf(outbuf),1,0);
3019 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3020 start_index, max_count));
3023 print_queue_struct *queue = NULL;
3024 char *p = smb_buf(outbuf) + 3;
3025 int count = print_queue_status(SNUM(conn), &queue,NULL);
3026 int num_to_get = ABS(max_count);
3027 int first = (max_count>0?start_index:start_index+max_count+1);
3028 int i;
3030 if (first >= count)
3031 num_to_get = 0;
3032 else
3033 num_to_get = MIN(num_to_get,count-first);
3036 for (i=first;i<first+num_to_get;i++) {
3037 put_dos_date2(p,0,queue[i].time);
3038 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
3039 SSVAL(p,5, queue[i].job);
3040 SIVAL(p,7,queue[i].size);
3041 CVAL(p,11) = 0;
3042 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
3043 p += 28;
3046 if (count > 0) {
3047 outsize = set_message(outbuf,2,28*count+3,False);
3048 SSVAL(outbuf,smb_vwv0,count);
3049 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3050 CVAL(smb_buf(outbuf),0) = 1;
3051 SSVAL(smb_buf(outbuf),1,28*count);
3054 SAFE_FREE(queue);
3056 DEBUG(3,("%d entries returned in queue\n",count));
3059 END_PROFILE(SMBsplretq);
3060 return(outsize);
3064 /****************************************************************************
3065 reply to a printwrite
3066 ****************************************************************************/
3067 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3069 int numtowrite;
3070 int outsize = set_message(outbuf,0,0,True);
3071 char *data;
3072 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3073 START_PROFILE(SMBsplwr);
3075 if (!CAN_PRINT(conn)) {
3076 END_PROFILE(SMBsplwr);
3077 return ERROR_DOS(ERRDOS,ERRnoaccess);
3080 CHECK_FSP(fsp,conn);
3081 CHECK_WRITE(fsp);
3083 numtowrite = SVAL(smb_buf(inbuf),1);
3084 data = smb_buf(inbuf) + 3;
3086 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3087 END_PROFILE(SMBsplwr);
3088 return(UNIXERROR(ERRDOS,ERRnoaccess));
3091 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3093 END_PROFILE(SMBsplwr);
3094 return(outsize);
3098 /****************************************************************************
3099 The guts of the mkdir command, split out so it may be called by the NT SMB
3100 code.
3101 ****************************************************************************/
3102 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
3104 BOOL bad_path = False;
3105 SMB_STRUCT_STAT sbuf;
3106 int ret= -1;
3108 unix_convert(directory,conn,0,&bad_path,&sbuf);
3110 if (check_name(directory, conn))
3111 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
3113 if (ret == -1) {
3114 return map_nt_error_from_unix(errno);
3117 return NT_STATUS_OK;
3120 /****************************************************************************
3121 Reply to a mkdir.
3122 ****************************************************************************/
3124 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3126 pstring directory;
3127 int outsize;
3128 NTSTATUS status;
3129 START_PROFILE(SMBmkdir);
3131 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3133 status = mkdir_internal(conn, directory);
3134 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
3136 outsize = set_message(outbuf,0,0,True);
3138 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3140 END_PROFILE(SMBmkdir);
3141 return(outsize);
3144 /****************************************************************************
3145 Static function used by reply_rmdir to delete an entire directory
3146 tree recursively. Return False on ok, True on fail.
3147 ****************************************************************************/
3149 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3151 char *dname = NULL;
3152 BOOL ret = False;
3153 void *dirptr = OpenDir(conn, directory, False);
3155 if(dirptr == NULL)
3156 return True;
3158 while((dname = ReadDirName(dirptr))) {
3159 pstring fullname;
3160 SMB_STRUCT_STAT st;
3162 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3163 continue;
3165 /* Construct the full name. */
3166 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3167 errno = ENOMEM;
3168 ret = True;
3169 break;
3172 pstrcpy(fullname, directory);
3173 pstrcat(fullname, "/");
3174 pstrcat(fullname, dname);
3176 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
3177 ret = True;
3178 break;
3181 if(st.st_mode & S_IFDIR) {
3182 if(recursive_rmdir(conn, fullname)!=0) {
3183 ret = True;
3184 break;
3186 if(vfs_rmdir(conn,fullname) != 0) {
3187 ret = True;
3188 break;
3190 } else if(vfs_unlink(conn,fullname) != 0) {
3191 ret = True;
3192 break;
3195 CloseDir(dirptr);
3196 return ret;
3199 /****************************************************************************
3200 The internals of the rmdir code - called elsewhere.
3201 ****************************************************************************/
3203 BOOL rmdir_internals(connection_struct *conn, char *directory)
3205 BOOL ok;
3207 ok = (vfs_rmdir(conn,directory) == 0);
3208 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3210 * Check to see if the only thing in this directory are
3211 * vetoed files/directories. If so then delete them and
3212 * retry. If we fail to delete any of them (and we *don't*
3213 * do a recursive delete) then fail the rmdir.
3215 BOOL all_veto_files = True;
3216 char *dname;
3217 void *dirptr = OpenDir(conn, directory, False);
3219 if(dirptr != NULL) {
3220 int dirpos = TellDir(dirptr);
3221 while ((dname = ReadDirName(dirptr))) {
3222 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3223 continue;
3224 if(!IS_VETO_PATH(conn, dname)) {
3225 all_veto_files = False;
3226 break;
3230 if(all_veto_files) {
3231 SeekDir(dirptr,dirpos);
3232 while ((dname = ReadDirName(dirptr))) {
3233 pstring fullname;
3234 SMB_STRUCT_STAT st;
3236 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3237 continue;
3239 /* Construct the full name. */
3240 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3241 errno = ENOMEM;
3242 break;
3245 pstrcpy(fullname, directory);
3246 pstrcat(fullname, "/");
3247 pstrcat(fullname, dname);
3249 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
3250 break;
3251 if(st.st_mode & S_IFDIR) {
3252 if(lp_recursive_veto_delete(SNUM(conn))) {
3253 if(recursive_rmdir(conn, fullname) != 0)
3254 break;
3256 if(vfs_rmdir(conn,fullname) != 0)
3257 break;
3258 } else if(vfs_unlink(conn,fullname) != 0)
3259 break;
3261 CloseDir(dirptr);
3262 /* Retry the rmdir */
3263 ok = (vfs_rmdir(conn,directory) == 0);
3264 } else {
3265 CloseDir(dirptr);
3267 } else {
3268 errno = ENOTEMPTY;
3272 if (!ok)
3273 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3275 return ok;
3278 /****************************************************************************
3279 Reply to a rmdir.
3280 ****************************************************************************/
3282 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3284 pstring directory;
3285 int outsize = 0;
3286 BOOL ok = False;
3287 BOOL bad_path = False;
3288 SMB_STRUCT_STAT sbuf;
3289 START_PROFILE(SMBrmdir);
3291 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
3293 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3295 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3297 if (check_name(directory,conn))
3299 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3300 ok = rmdir_internals(conn, directory);
3303 if (!ok)
3305 if((errno == ENOENT) && bad_path)
3307 unix_ERR_class = ERRDOS;
3308 unix_ERR_code = ERRbadpath;
3310 END_PROFILE(SMBrmdir);
3311 return(UNIXERROR(ERRDOS,ERRbadpath));
3314 outsize = set_message(outbuf,0,0,True);
3316 DEBUG( 3, ( "rmdir %s\n", directory ) );
3318 END_PROFILE(SMBrmdir);
3319 return(outsize);
3323 /*******************************************************************
3324 resolve wildcards in a filename rename
3325 ********************************************************************/
3326 static BOOL resolve_wildcards(char *name1,char *name2)
3328 fstring root1,root2;
3329 fstring ext1,ext2;
3330 char *p,*p2;
3332 name1 = strrchr_m(name1,'/');
3333 name2 = strrchr_m(name2,'/');
3335 if (!name1 || !name2) return(False);
3337 fstrcpy(root1,name1);
3338 fstrcpy(root2,name2);
3339 p = strrchr_m(root1,'.');
3340 if (p) {
3341 *p = 0;
3342 fstrcpy(ext1,p+1);
3343 } else {
3344 fstrcpy(ext1,"");
3346 p = strrchr_m(root2,'.');
3347 if (p) {
3348 *p = 0;
3349 fstrcpy(ext2,p+1);
3350 } else {
3351 fstrcpy(ext2,"");
3354 p = root1;
3355 p2 = root2;
3356 while (*p2) {
3357 if (*p2 == '?') {
3358 *p2 = *p;
3359 p2++;
3360 } else {
3361 p2++;
3363 if (*p) p++;
3366 p = ext1;
3367 p2 = ext2;
3368 while (*p2) {
3369 if (*p2 == '?') {
3370 *p2 = *p;
3371 p2++;
3372 } else {
3373 p2++;
3375 if (*p) p++;
3378 pstrcpy(name2,root2);
3379 if (ext2[0]) {
3380 pstrcat(name2,".");
3381 pstrcat(name2,ext2);
3384 return(True);
3387 /*******************************************************************
3388 check if a user is allowed to rename a file
3389 ********************************************************************/
3390 static BOOL can_rename(char *fname,connection_struct *conn)
3392 SMB_STRUCT_STAT sbuf;
3394 if (!CAN_WRITE(conn)) return(False);
3396 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
3397 if (!check_file_sharing(conn,fname,True)) return(False);
3398 return(True);
3401 /****************************************************************************
3402 The guts of the rename command, split out so it may be called by the NT SMB
3403 code.
3404 ****************************************************************************/
3405 NTSTATUS rename_internals(connection_struct *conn,
3406 char *name,
3407 char *newname, BOOL replace_if_exists)
3409 pstring directory;
3410 pstring mask;
3411 pstring newname_last_component;
3412 char *p;
3413 BOOL has_wild;
3414 BOOL bad_path1 = False;
3415 BOOL bad_path2 = False;
3416 int count=0;
3417 NTSTATUS error = NT_STATUS_OK;
3418 BOOL exists=False;
3419 BOOL rc = True;
3420 SMB_STRUCT_STAT sbuf1, sbuf2;
3422 *directory = *mask = 0;
3424 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3425 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3428 * Split the old name into directory and last component
3429 * strings. Note that unix_convert may have stripped off a
3430 * leading ./ from both name and newname if the rename is
3431 * at the root of the share. We need to make sure either both
3432 * name and newname contain a / character or neither of them do
3433 * as this is checked in resolve_wildcards().
3436 p = strrchr_m(name,'/');
3437 if (!p) {
3438 pstrcpy(directory,".");
3439 pstrcpy(mask,name);
3440 } else {
3441 *p = 0;
3442 pstrcpy(directory,name);
3443 pstrcpy(mask,p+1);
3444 *p = '/'; /* Replace needed for exceptional test below. */
3448 * We should only check the mangled cache
3449 * here if unix_convert failed. This means
3450 * that the path in 'mask' doesn't exist
3451 * on the file system and so we need to look
3452 * for a possible mangle. This patch from
3453 * Tine Smukavec <valentin.smukavec@hermes.si>.
3456 if (!rc && is_mangled(mask))
3457 check_mangled_cache( mask );
3459 has_wild = ms_has_wild(mask);
3461 if (!has_wild) {
3463 * No wildcards - just process the one file.
3465 BOOL is_short_name = is_8_3(name, True);
3467 /* Add a terminating '/' to the directory name. */
3468 pstrcat(directory,"/");
3469 pstrcat(directory,mask);
3471 /* Ensure newname contains a '/' also */
3472 if(strrchr_m(newname,'/') == 0) {
3473 pstring tmpstr;
3475 pstrcpy(tmpstr, "./");
3476 pstrcat(tmpstr, newname);
3477 pstrcpy(newname, tmpstr);
3480 DEBUG(3,("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",
3481 case_sensitive, case_preserve, short_case_preserve, directory,
3482 newname, newname_last_component, is_short_name));
3485 * Check for special case with case preserving and not
3486 * case sensitive, if directory and newname are identical,
3487 * and the old last component differs from the original
3488 * last component only by case, then we should allow
3489 * the rename (user is trying to change the case of the
3490 * filename).
3492 if((case_sensitive == False) &&
3493 (((case_preserve == True) &&
3494 (is_short_name == False)) ||
3495 ((short_case_preserve == True) &&
3496 (is_short_name == True))) &&
3497 strcsequal(directory, newname)) {
3498 pstring newname_modified_last_component;
3501 * Get the last component of the modified name.
3502 * Note that we guarantee that newname contains a '/'
3503 * character above.
3505 p = strrchr_m(newname,'/');
3506 pstrcpy(newname_modified_last_component,p+1);
3508 if(strcsequal(newname_modified_last_component,
3509 newname_last_component) == False) {
3511 * Replace the modified last component with
3512 * the original.
3514 pstrcpy(p+1, newname_last_component);
3518 if(replace_if_exists) {
3520 * NT SMB specific flag - rename can overwrite
3521 * file with the same name so don't check for
3522 * vfs_file_exist().
3525 if(resolve_wildcards(directory,newname) &&
3526 can_rename(directory,conn) &&
3527 conn->vfs_ops.rename(conn,directory,newname) == 0)
3528 count++;
3529 } else {
3530 if (resolve_wildcards(directory,newname) &&
3531 can_rename(directory,conn) &&
3532 !vfs_file_exist(conn,newname,NULL) &&
3533 conn->vfs_ops.rename(conn,directory,newname) == 0)
3534 count++;
3537 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3538 directory,newname));
3540 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3541 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3542 exists = True;
3543 error = NT_STATUS_OBJECT_NAME_COLLISION;
3545 } else {
3547 * Wildcards - process each file that matches.
3549 void *dirptr = NULL;
3550 char *dname;
3551 pstring destname;
3553 if (check_name(directory,conn))
3554 dirptr = OpenDir(conn, directory, True);
3556 if (dirptr) {
3557 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3559 if (strequal(mask,"????????.???"))
3560 pstrcpy(mask,"*");
3562 while ((dname = ReadDirName(dirptr))) {
3563 pstring fname;
3565 pstrcpy(fname,dname);
3567 if(!mask_match(fname, mask, case_sensitive))
3568 continue;
3570 error = NT_STATUS_ACCESS_DENIED;
3571 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3572 if (!can_rename(fname,conn)) {
3573 DEBUG(6,("rename %s refused\n", fname));
3574 continue;
3576 pstrcpy(destname,newname);
3578 if (!resolve_wildcards(fname,destname)) {
3579 DEBUG(6,("resolve_wildcards %s %s failed\n",
3580 fname, destname));
3581 continue;
3584 if (!replace_if_exists &&
3585 vfs_file_exist(conn,destname, NULL)) {
3586 DEBUG(6,("file_exist %s\n", destname));
3587 error = NT_STATUS_OBJECT_NAME_COLLISION;
3588 continue;
3591 if (!conn->vfs_ops.rename(conn,fname,destname))
3592 count++;
3593 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3595 CloseDir(dirptr);
3599 if (count == 0 && NT_STATUS_IS_OK(error)) {
3600 error = map_nt_error_from_unix(errno);
3603 return error;
3606 /****************************************************************************
3607 Reply to a mv.
3608 ****************************************************************************/
3610 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3611 int dum_buffsize)
3613 int outsize = 0;
3614 pstring name;
3615 pstring newname;
3616 char *p;
3617 NTSTATUS status;
3619 START_PROFILE(SMBmv);
3621 p = smb_buf(inbuf) + 1;
3622 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3623 p++;
3624 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3626 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3627 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3629 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3631 status = rename_internals(conn, name, newname, False);
3632 if (!NT_STATUS_IS_OK(status)) {
3633 return ERROR_NT(status);
3637 * Win2k needs a changenotify request response before it will
3638 * update after a rename..
3640 process_pending_change_notify_queue((time_t)0);
3641 outsize = set_message(outbuf,0,0,True);
3643 END_PROFILE(SMBmv);
3644 return(outsize);
3647 /*******************************************************************
3648 Copy a file as part of a reply_copy.
3649 ******************************************************************/
3651 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3652 int count,BOOL target_is_directory, int *err_ret)
3654 int Access,action;
3655 SMB_STRUCT_STAT src_sbuf, sbuf2;
3656 SMB_OFF_T ret=-1;
3657 files_struct *fsp1,*fsp2;
3658 pstring dest;
3660 *err_ret = 0;
3662 pstrcpy(dest,dest1);
3663 if (target_is_directory) {
3664 char *p = strrchr_m(src,'/');
3665 if (p)
3666 p++;
3667 else
3668 p = src;
3669 pstrcat(dest,"/");
3670 pstrcat(dest,p);
3673 if (!vfs_file_exist(conn,src,&src_sbuf))
3674 return(False);
3676 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3677 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3679 if (!fsp1)
3680 return(False);
3682 if (!target_is_directory && count)
3683 ofun = FILE_EXISTS_OPEN;
3685 if (vfs_stat(conn,dest,&sbuf2) == -1)
3686 ZERO_STRUCTP(&sbuf2);
3688 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3689 ofun,src_sbuf.st_mode,0,&Access,&action);
3691 if (!fsp2) {
3692 close_file(fsp1,False);
3693 return(False);
3696 if ((ofun&3) == 1) {
3697 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3698 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3700 * Stop the copy from occurring.
3702 ret = -1;
3703 src_sbuf.st_size = 0;
3707 if (src_sbuf.st_size)
3708 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3710 close_file(fsp1,False);
3712 * As we are opening fsp1 read-only we only expect
3713 * an error on close on fsp2 if we are out of space.
3714 * Thus we don't look at the error return from the
3715 * close of fsp1.
3717 *err_ret = close_file(fsp2,False);
3719 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3722 /****************************************************************************
3723 reply to a file copy.
3724 ****************************************************************************/
3725 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3727 int outsize = 0;
3728 pstring name;
3729 pstring directory;
3730 pstring mask,newname;
3731 char *p;
3732 int count=0;
3733 int error = ERRnoaccess;
3734 int err = 0;
3735 BOOL has_wild;
3736 BOOL exists=False;
3737 int tid2 = SVAL(inbuf,smb_vwv0);
3738 int ofun = SVAL(inbuf,smb_vwv1);
3739 int flags = SVAL(inbuf,smb_vwv2);
3740 BOOL target_is_directory=False;
3741 BOOL bad_path1 = False;
3742 BOOL bad_path2 = False;
3743 BOOL rc = True;
3744 SMB_STRUCT_STAT sbuf1, sbuf2;
3745 START_PROFILE(SMBcopy);
3747 *directory = *mask = 0;
3749 p = smb_buf(inbuf);
3750 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3751 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3753 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3755 if (tid2 != conn->cnum) {
3756 /* can't currently handle inter share copies XXXX */
3757 DEBUG(3,("Rejecting inter-share copy\n"));
3758 END_PROFILE(SMBcopy);
3759 return ERROR_DOS(ERRSRV,ERRinvdevice);
3762 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3763 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3765 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3766 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3768 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3770 if ((flags&1) && target_is_directory) {
3771 END_PROFILE(SMBcopy);
3772 return ERROR_DOS(ERRDOS,ERRbadfile);
3775 if ((flags&2) && !target_is_directory) {
3776 END_PROFILE(SMBcopy);
3777 return ERROR_DOS(ERRDOS,ERRbadpath);
3780 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3781 /* wants a tree copy! XXXX */
3782 DEBUG(3,("Rejecting tree copy\n"));
3783 END_PROFILE(SMBcopy);
3784 return ERROR_DOS(ERRSRV,ERRerror);
3787 p = strrchr_m(name,'/');
3788 if (!p) {
3789 pstrcpy(directory,"./");
3790 pstrcpy(mask,name);
3791 } else {
3792 *p = 0;
3793 pstrcpy(directory,name);
3794 pstrcpy(mask,p+1);
3798 * We should only check the mangled cache
3799 * here if unix_convert failed. This means
3800 * that the path in 'mask' doesn't exist
3801 * on the file system and so we need to look
3802 * for a possible mangle. This patch from
3803 * Tine Smukavec <valentin.smukavec@hermes.si>.
3806 if (!rc && is_mangled(mask))
3807 check_mangled_cache( mask );
3809 has_wild = ms_has_wild(mask);
3811 if (!has_wild) {
3812 pstrcat(directory,"/");
3813 pstrcat(directory,mask);
3814 if (resolve_wildcards(directory,newname) &&
3815 copy_file(directory,newname,conn,ofun,
3816 count,target_is_directory,&err)) count++;
3817 if(!count && err) {
3818 errno = err;
3819 END_PROFILE(SMBcopy);
3820 return(UNIXERROR(ERRHRD,ERRgeneral));
3822 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3823 } else {
3824 void *dirptr = NULL;
3825 char *dname;
3826 pstring destname;
3828 if (check_name(directory,conn))
3829 dirptr = OpenDir(conn, directory, True);
3831 if (dirptr) {
3832 error = ERRbadfile;
3834 if (strequal(mask,"????????.???"))
3835 pstrcpy(mask,"*");
3837 while ((dname = ReadDirName(dirptr))) {
3838 pstring fname;
3839 pstrcpy(fname,dname);
3841 if(!mask_match(fname, mask, case_sensitive))
3842 continue;
3844 error = ERRnoaccess;
3845 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3846 pstrcpy(destname,newname);
3847 if (resolve_wildcards(fname,destname) &&
3848 copy_file(fname,destname,conn,ofun,
3849 count,target_is_directory,&err)) count++;
3850 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3852 CloseDir(dirptr);
3856 if (count == 0) {
3857 if(err) {
3858 /* Error on close... */
3859 errno = err;
3860 END_PROFILE(SMBcopy);
3861 return(UNIXERROR(ERRHRD,ERRgeneral));
3864 if (exists) {
3865 END_PROFILE(SMBcopy);
3866 return ERROR_DOS(ERRDOS,error);
3867 } else
3869 if((errno == ENOENT) && (bad_path1 || bad_path2))
3871 unix_ERR_class = ERRDOS;
3872 unix_ERR_code = ERRbadpath;
3874 END_PROFILE(SMBcopy);
3875 return(UNIXERROR(ERRDOS,error));
3879 outsize = set_message(outbuf,1,0,True);
3880 SSVAL(outbuf,smb_vwv0,count);
3882 END_PROFILE(SMBcopy);
3883 return(outsize);
3886 /****************************************************************************
3887 reply to a setdir
3888 ****************************************************************************/
3889 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3891 int snum;
3892 int outsize = 0;
3893 BOOL ok = False;
3894 pstring newdir;
3895 START_PROFILE(pathworks_setdir);
3897 snum = SNUM(conn);
3898 if (!CAN_SETDIR(snum)) {
3899 END_PROFILE(pathworks_setdir);
3900 return ERROR_DOS(ERRDOS,ERRnoaccess);
3903 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
3905 if (strlen(newdir) == 0) {
3906 ok = True;
3907 } else {
3908 ok = vfs_directory_exist(conn,newdir,NULL);
3909 if (ok) {
3910 string_set(&conn->connectpath,newdir);
3914 if (!ok) {
3915 END_PROFILE(pathworks_setdir);
3916 return ERROR_DOS(ERRDOS,ERRbadpath);
3919 outsize = set_message(outbuf,0,0,True);
3920 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3922 DEBUG(3,("setdir %s\n", newdir));
3924 END_PROFILE(pathworks_setdir);
3925 return(outsize);
3928 /****************************************************************************
3929 Get a lock pid, dealing with large count requests.
3930 ****************************************************************************/
3932 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3934 if(!large_file_format)
3935 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3936 else
3937 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
3940 /****************************************************************************
3941 Get a lock count, dealing with large count requests.
3942 ****************************************************************************/
3944 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3946 SMB_BIG_UINT count = 0;
3948 if(!large_file_format) {
3949 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3950 } else {
3952 #if defined(HAVE_LONGLONG)
3953 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3954 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3955 #else /* HAVE_LONGLONG */
3958 * NT4.x seems to be broken in that it sends large file (64 bit)
3959 * lockingX calls even if the CAP_LARGE_FILES was *not*
3960 * negotiated. For boxes without large unsigned ints truncate the
3961 * lock count by dropping the top 32 bits.
3964 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3965 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3966 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3967 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3968 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3971 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3972 #endif /* HAVE_LONGLONG */
3975 return count;
3978 #if !defined(HAVE_LONGLONG)
3979 /****************************************************************************
3980 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3981 ****************************************************************************/
3982 static uint32 map_lock_offset(uint32 high, uint32 low)
3984 unsigned int i;
3985 uint32 mask = 0;
3986 uint32 highcopy = high;
3989 * Try and find out how many significant bits there are in high.
3992 for(i = 0; highcopy; i++)
3993 highcopy >>= 1;
3996 * We use 31 bits not 32 here as POSIX
3997 * lock offsets may not be negative.
4000 mask = (~0) << (31 - i);
4002 if(low & mask)
4003 return 0; /* Fail. */
4005 high <<= (31 - i);
4007 return (high|low);
4009 #endif /* !defined(HAVE_LONGLONG) */
4011 /****************************************************************************
4012 Get a lock offset, dealing with large offset requests.
4013 ****************************************************************************/
4015 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4017 SMB_BIG_UINT offset = 0;
4019 *err = False;
4021 if(!large_file_format) {
4022 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4023 } else {
4025 #if defined(HAVE_LONGLONG)
4026 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4027 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4028 #else /* HAVE_LONGLONG */
4031 * NT4.x seems to be broken in that it sends large file (64 bit)
4032 * lockingX calls even if the CAP_LARGE_FILES was *not*
4033 * negotiated. For boxes without large unsigned ints mangle the
4034 * lock offset by mapping the top 32 bits onto the lower 32.
4037 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4038 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4039 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4040 uint32 new_low = 0;
4042 if((new_low = map_lock_offset(high, low)) == 0) {
4043 *err = True;
4044 return (SMB_BIG_UINT)-1;
4047 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4048 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4049 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4050 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4053 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4054 #endif /* HAVE_LONGLONG */
4057 return offset;
4060 /****************************************************************************
4061 reply to a lockingX request
4062 ****************************************************************************/
4064 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4066 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4067 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4068 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4069 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4070 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4071 SMB_BIG_UINT count = 0, offset = 0;
4072 uint16 lock_pid;
4073 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4074 int i;
4075 char *data;
4076 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4077 BOOL err;
4078 NTSTATUS status;
4080 START_PROFILE(SMBlockingX);
4082 CHECK_FSP(fsp,conn);
4084 data = smb_buf(inbuf);
4086 /* Check if this is an oplock break on a file
4087 we have granted an oplock on.
4089 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4090 /* Client can insist on breaking to none. */
4091 BOOL break_to_none = (oplocklevel == 0);
4093 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4094 (unsigned int)oplocklevel, fsp->fnum ));
4097 * Make sure we have granted an exclusive or batch oplock on this file.
4100 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4101 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4102 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4104 /* if this is a pure oplock break request then don't send a reply */
4105 if (num_locks == 0 && num_ulocks == 0) {
4106 END_PROFILE(SMBlockingX);
4107 return -1;
4108 } else {
4109 END_PROFILE(SMBlockingX);
4110 return ERROR_DOS(ERRDOS,ERRlock);
4114 if (remove_oplock(fsp, break_to_none) == False) {
4115 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4116 fsp->fsp_name ));
4119 /* if this is a pure oplock break request then don't send a reply */
4120 if (num_locks == 0 && num_ulocks == 0) {
4121 /* Sanity check - ensure a pure oplock break is not a
4122 chained request. */
4123 if(CVAL(inbuf,smb_vwv0) != 0xff)
4124 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4125 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4126 END_PROFILE(SMBlockingX);
4127 return -1;
4132 * We do this check *after* we have checked this is not a oplock break
4133 * response message. JRA.
4136 release_level_2_oplocks_on_change(fsp);
4138 /* Data now points at the beginning of the list
4139 of smb_unlkrng structs */
4140 for(i = 0; i < (int)num_ulocks; i++) {
4141 lock_pid = get_lock_pid( data, i, large_file_format);
4142 count = get_lock_count( data, i, large_file_format);
4143 offset = get_lock_offset( data, i, large_file_format, &err);
4146 * There is no error code marked "stupid client bug".... :-).
4148 if(err) {
4149 END_PROFILE(SMBlockingX);
4150 return ERROR_DOS(ERRDOS,ERRnoaccess);
4153 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4154 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4156 status = do_unlock(fsp,conn,lock_pid,count,offset);
4157 if (NT_STATUS_V(status)) {
4158 END_PROFILE(SMBlockingX);
4159 return ERROR_NT(status);
4163 /* Setup the timeout in seconds. */
4164 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
4166 /* Now do any requested locks */
4167 data += ((large_file_format ? 20 : 10)*num_ulocks);
4169 /* Data now points at the beginning of the list
4170 of smb_lkrng structs */
4172 for(i = 0; i < (int)num_locks; i++) {
4173 lock_pid = get_lock_pid( data, i, large_file_format);
4174 count = get_lock_count( data, i, large_file_format);
4175 offset = get_lock_offset( data, i, large_file_format, &err);
4178 * There is no error code marked "stupid client bug".... :-).
4180 if(err) {
4181 END_PROFILE(SMBlockingX);
4182 return ERROR_DOS(ERRDOS,ERRnoaccess);
4185 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
4186 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4188 status = do_lock(fsp,conn,lock_pid, count,offset,
4189 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4190 if (NT_STATUS_V(status)) {
4191 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
4193 * A blocking lock was requested. Package up
4194 * this smb into a queued request and push it
4195 * onto the blocking lock queue.
4197 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
4198 END_PROFILE(SMBlockingX);
4199 return -1;
4202 break;
4206 /* If any of the above locks failed, then we must unlock
4207 all of the previous locks (X/Open spec). */
4208 if (i != num_locks && num_locks != 0) {
4210 * Ensure we don't do a remove on the lock that just failed,
4211 * as under POSIX rules, if we have a lock already there, we
4212 * will delete it (and we shouldn't) .....
4214 for(i--; i >= 0; i--) {
4215 lock_pid = get_lock_pid( data, i, large_file_format);
4216 count = get_lock_count( data, i, large_file_format);
4217 offset = get_lock_offset( data, i, large_file_format, &err);
4220 * There is no error code marked "stupid client bug".... :-).
4222 if(err) {
4223 END_PROFILE(SMBlockingX);
4224 return ERROR_DOS(ERRDOS,ERRnoaccess);
4227 do_unlock(fsp,conn,lock_pid,count,offset);
4229 END_PROFILE(SMBlockingX);
4230 return ERROR_NT(status);
4233 set_message(outbuf,2,0,True);
4235 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4236 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4238 END_PROFILE(SMBlockingX);
4239 return chain_reply(inbuf,outbuf,length,bufsize);
4243 /****************************************************************************
4244 reply to a SMBreadbmpx (read block multiplex) request
4245 ****************************************************************************/
4246 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4248 ssize_t nread = -1;
4249 ssize_t total_read;
4250 char *data;
4251 SMB_OFF_T startpos;
4252 int outsize;
4253 size_t maxcount;
4254 int max_per_packet;
4255 size_t tcount;
4256 int pad;
4257 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4258 START_PROFILE(SMBreadBmpx);
4260 /* this function doesn't seem to work - disable by default */
4261 if (!lp_readbmpx()) {
4262 END_PROFILE(SMBreadBmpx);
4263 return ERROR_DOS(ERRSRV,ERRuseSTD);
4266 outsize = set_message(outbuf,8,0,True);
4268 CHECK_FSP(fsp,conn);
4269 CHECK_READ(fsp);
4271 startpos = IVAL(inbuf,smb_vwv1);
4272 maxcount = SVAL(inbuf,smb_vwv3);
4274 data = smb_buf(outbuf);
4275 pad = ((long)data)%4;
4276 if (pad) pad = 4 - pad;
4277 data += pad;
4279 max_per_packet = bufsize-(outsize+pad);
4280 tcount = maxcount;
4281 total_read = 0;
4283 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4284 END_PROFILE(SMBreadBmpx);
4285 return ERROR_DOS(ERRDOS,ERRlock);
4290 size_t N = MIN(max_per_packet,tcount-total_read);
4292 nread = read_file(fsp,data,startpos,N);
4294 if (nread <= 0) nread = 0;
4296 if (nread < (ssize_t)N)
4297 tcount = total_read + nread;
4299 set_message(outbuf,8,nread,False);
4300 SIVAL(outbuf,smb_vwv0,startpos);
4301 SSVAL(outbuf,smb_vwv2,tcount);
4302 SSVAL(outbuf,smb_vwv6,nread);
4303 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4305 if (!send_smb(smbd_server_fd(),outbuf))
4306 exit_server("reply_readbmpx: send_smb failed.\n");
4308 total_read += nread;
4309 startpos += nread;
4311 while (total_read < (ssize_t)tcount);
4313 END_PROFILE(SMBreadBmpx);
4314 return(-1);
4318 /****************************************************************************
4319 reply to a SMBsetattrE
4320 ****************************************************************************/
4322 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4324 struct utimbuf unix_times;
4325 int outsize = 0;
4326 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4327 START_PROFILE(SMBsetattrE);
4329 outsize = set_message(outbuf,0,0,True);
4331 CHECK_FSP(fsp,conn);
4333 /* Convert the DOS times into unix times. Ignore create
4334 time as UNIX can't set this.
4336 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4337 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4340 * Patch from Ray Frush <frush@engr.colostate.edu>
4341 * Sometimes times are sent as zero - ignore them.
4344 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
4346 /* Ignore request */
4347 if( DEBUGLVL( 3 ) )
4349 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4350 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4352 END_PROFILE(SMBsetattrE);
4353 return(outsize);
4355 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
4357 /* set modify time = to access time if modify time was 0 */
4358 unix_times.modtime = unix_times.actime;
4361 /* Set the date on this file */
4362 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4363 END_PROFILE(SMBsetattrE);
4364 return ERROR_DOS(ERRDOS,ERRnoaccess);
4367 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4368 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4370 END_PROFILE(SMBsetattrE);
4371 return(outsize);
4375 /****************************************************************************
4376 reply to a SMBgetattrE
4377 ****************************************************************************/
4379 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4381 SMB_STRUCT_STAT sbuf;
4382 int outsize = 0;
4383 int mode;
4384 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4385 START_PROFILE(SMBgetattrE);
4387 outsize = set_message(outbuf,11,0,True);
4389 CHECK_FSP(fsp,conn);
4391 /* Do an fstat on this file */
4392 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4393 END_PROFILE(SMBgetattrE);
4394 return(UNIXERROR(ERRDOS,ERRnoaccess));
4397 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4399 /* Convert the times into dos times. Set create
4400 date to be last modify date as UNIX doesn't save
4401 this */
4402 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4403 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4404 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4405 if (mode & aDIR)
4407 SIVAL(outbuf,smb_vwv6,0);
4408 SIVAL(outbuf,smb_vwv8,0);
4410 else
4412 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4413 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4415 SSVAL(outbuf,smb_vwv10, mode);
4417 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4419 END_PROFILE(SMBgetattrE);
4420 return(outsize);