2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
32 extern char magic_char
;
33 extern BOOL case_sensitive
;
34 extern BOOL case_preserve
;
35 extern BOOL short_case_preserve
;
36 extern int global_oplock_break
;
37 unsigned int smb_echo_count
= 0;
39 extern BOOL global_encrypted_passwords_negotiated
;
41 /****************************************************************************
42 Reply to an special message.
43 ****************************************************************************/
45 int reply_special(char *inbuf
,char *outbuf
)
48 int msg_type
= CVAL(inbuf
,0);
49 int msg_flags
= CVAL(inbuf
,1);
55 static BOOL already_got_session
= False
;
59 memset(outbuf
,'\0',smb_size
);
64 case 0x81: /* session request */
66 if (already_got_session
) {
67 exit_server("multiple session request not permitted");
72 if (name_len(inbuf
+4) > 50 ||
73 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
74 DEBUG(0,("Invalid name length in session request\n"));
77 name_extract(inbuf
,4,name1
);
78 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
79 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
86 name_type
= name2
[15];
90 set_local_machine_name(name1
, True
);
91 set_remote_machine_name(name2
, True
);
93 DEBUG(2,("netbios connect: local=%s remote=%s\n",
94 get_local_machine_name(), get_remote_machine_name() ));
96 if (name_type
== 'R') {
97 /* We are being asked for a pathworks session ---
99 SCVAL(outbuf
, 0,0x83);
103 /* only add the client's machine name to the list
104 of possibly valid usernames if we are operating
105 in share mode security */
106 if (lp_security() == SEC_SHARE
) {
107 add_session_user(get_remote_machine_name());
110 reload_services(True
);
113 claim_connection(NULL
,"",0,True
,FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
);
115 already_got_session
= True
;
118 case 0x89: /* session keepalive request
119 (some old clients produce this?) */
120 SCVAL(outbuf
,0,SMBkeepalive
);
124 case 0x82: /* positive session response */
125 case 0x83: /* negative session response */
126 case 0x84: /* retarget session response */
127 DEBUG(0,("Unexpected session response\n"));
130 case SMBkeepalive
: /* session keepalive */
135 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
136 msg_type
, msg_flags
));
141 /****************************************************************************
143 ****************************************************************************/
145 int reply_tcon(connection_struct
*conn
,
146 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
153 uint16 vuid
= SVAL(inbuf
,smb_uid
);
157 DATA_BLOB password_blob
;
159 START_PROFILE(SMBtcon
);
161 *service_buf
= *password
= *dev
= 0;
163 p
= smb_buf(inbuf
)+1;
164 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service_buf
), STR_TERMINATE
) + 1;
165 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
167 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
169 p
= strrchr_m(service_buf
,'\\');
173 service
= service_buf
;
176 password_blob
= data_blob(password
, pwlen
+1);
178 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
180 data_blob_clear_free(&password_blob
);
183 END_PROFILE(SMBtcon
);
184 return ERROR_NT(nt_status
);
187 outsize
= set_message(outbuf
,2,0,True
);
188 SSVAL(outbuf
,smb_vwv0
,max_recv
);
189 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
190 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
192 DEBUG(3,("tcon service=%s cnum=%d\n",
193 service
, conn
->cnum
));
195 END_PROFILE(SMBtcon
);
199 /****************************************************************************
200 Reply to a tcon and X.
201 ****************************************************************************/
203 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
208 /* what the cleint thinks the device is */
209 fstring client_devicetype
;
210 /* what the server tells the client the share represents */
211 const char *server_devicetype
;
213 uint16 vuid
= SVAL(inbuf
,smb_uid
);
214 int passlen
= SVAL(inbuf
,smb_vwv3
);
217 extern BOOL global_encrypted_passwords_negotiated
;
219 START_PROFILE(SMBtconX
);
221 *service
= *client_devicetype
= 0;
223 /* we might have to close an old one */
224 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
225 close_cnum(conn
,vuid
);
228 if (passlen
> MAX_PASS_LEN
) {
229 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
232 if (global_encrypted_passwords_negotiated
) {
233 password
= data_blob(smb_buf(inbuf
),passlen
);
235 password
= data_blob(smb_buf(inbuf
),passlen
+1);
236 /* Ensure correct termination */
237 password
.data
[passlen
]=0;
240 p
= smb_buf(inbuf
) + passlen
;
241 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
244 * the service name can be either: \\server\share
245 * or share directly like on the DELL PowerVault 705
248 q
= strchr_m(path
+2,'\\');
250 END_PROFILE(SMBtconX
);
251 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
253 fstrcpy(service
,q
+1);
256 fstrcpy(service
,path
);
258 p
+= srvstr_pull(inbuf
, client_devicetype
, p
, sizeof(client_devicetype
), 6, STR_ASCII
);
260 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
262 conn
= make_connection(service
,password
,client_devicetype
,vuid
,&nt_status
);
264 data_blob_clear_free(&password
);
267 END_PROFILE(SMBtconX
);
268 return ERROR_NT(nt_status
);
272 server_devicetype
= "IPC";
273 else if ( IS_PRINT(conn
) )
274 server_devicetype
= "LPT1:";
276 server_devicetype
= "A:";
278 if (Protocol
< PROTOCOL_NT1
) {
279 set_message(outbuf
,2,0,True
);
281 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
282 STR_TERMINATE
|STR_ASCII
);
283 set_message_end(outbuf
,p
);
285 /* NT sets the fstype of IPC$ to the null string */
286 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
288 set_message(outbuf
,3,0,True
);
291 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
292 STR_TERMINATE
|STR_ASCII
);
293 p
+= srvstr_push(outbuf
, p
, fstype
, -1,
296 set_message_end(outbuf
,p
);
298 /* what does setting this bit do? It is set by NT4 and
299 may affect the ability to autorun mounted cdroms */
300 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
301 (lp_csc_policy(SNUM(conn
)) << 2));
303 init_dfsroot(conn
, inbuf
, outbuf
);
307 DEBUG(3,("tconX service=%s \n",
310 /* set the incoming and outgoing tid to the just created one */
311 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
312 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
314 END_PROFILE(SMBtconX
);
315 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
318 /****************************************************************************
319 Reply to an unknown type.
320 ****************************************************************************/
322 int reply_unknown(char *inbuf
,char *outbuf
)
325 type
= CVAL(inbuf
,smb_com
);
327 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
328 smb_fn_name(type
), type
, type
));
330 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
333 /****************************************************************************
335 ****************************************************************************/
337 int reply_ioctl(connection_struct
*conn
,
338 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
340 uint16 device
= SVAL(inbuf
,smb_vwv1
);
341 uint16 function
= SVAL(inbuf
,smb_vwv2
);
342 uint32 ioctl_code
= (device
<< 16) + function
;
343 int replysize
, outsize
;
345 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
346 START_PROFILE(SMBioctl
);
348 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
350 switch (ioctl_code
) {
351 case IOCTL_QUERY_JOB_INFO
:
355 END_PROFILE(SMBioctl
);
356 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
359 outsize
= set_message(outbuf
,8,replysize
+1,True
);
360 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
361 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
362 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
363 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
365 switch (ioctl_code
) {
366 case IOCTL_QUERY_JOB_INFO
:
368 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
369 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
370 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
375 END_PROFILE(SMBioctl
);
379 /****************************************************************************
381 ****************************************************************************/
383 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
389 BOOL bad_path
= False
;
390 SMB_STRUCT_STAT sbuf
;
391 START_PROFILE(SMBchkpth
);
393 srvstr_pull_buf(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), STR_TERMINATE
);
395 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
397 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
399 mode
= SVAL(inbuf
,smb_vwv0
);
401 if (check_name(name
,conn
)) {
402 if (VALID_STAT(sbuf
) || VFS_STAT(conn
,name
,&sbuf
) == 0)
403 if (!(ok
= S_ISDIR(sbuf
.st_mode
)))
408 /* We special case this - as when a Windows machine
409 is parsing a path is steps through the components
410 one at a time - if a component fails it expects
411 ERRbadpath, not ERRbadfile.
414 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
416 return(UNIXERROR(ERRDOS
,ERRbadpath
));
419 outsize
= set_message(outbuf
,0,0,True
);
421 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
423 END_PROFILE(SMBchkpth
);
427 /****************************************************************************
429 ****************************************************************************/
431 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
435 SMB_STRUCT_STAT sbuf
;
440 BOOL bad_path
= False
;
442 START_PROFILE(SMBgetatr
);
444 p
= smb_buf(inbuf
) + 1;
445 p
+= srvstr_pull_buf(inbuf
, fname
, p
, sizeof(fname
), STR_TERMINATE
);
447 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
449 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
450 under WfWg - weird! */
452 mode
= aHIDDEN
| aDIR
;
453 if (!CAN_WRITE(conn
))
459 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
460 if (check_name(fname
,conn
)) {
461 if (VALID_STAT(sbuf
) || VFS_STAT(conn
,fname
,&sbuf
) == 0) {
462 mode
= dos_mode(conn
,fname
,&sbuf
);
464 mtime
= sbuf
.st_mtime
;
469 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
475 set_bad_path_error(errno
, bad_path
);
476 END_PROFILE(SMBgetatr
);
477 return(UNIXERROR(ERRDOS
,ERRbadfile
));
480 outsize
= set_message(outbuf
,10,0,True
);
482 SSVAL(outbuf
,smb_vwv0
,mode
);
483 if(lp_dos_filetime_resolution(SNUM(conn
)) )
484 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
486 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
487 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
489 if (Protocol
>= PROTOCOL_NT1
)
490 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
492 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
494 END_PROFILE(SMBgetatr
);
498 /****************************************************************************
500 ****************************************************************************/
502 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
509 SMB_STRUCT_STAT sbuf
;
510 BOOL bad_path
= False
;
513 START_PROFILE(SMBsetatr
);
515 p
= smb_buf(inbuf
) + 1;
516 p
+= srvstr_pull_buf(inbuf
, fname
, p
, sizeof(fname
), STR_TERMINATE
);
517 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
519 mode
= SVAL(inbuf
,smb_vwv0
);
520 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
522 if (VALID_STAT_OF_DIR(sbuf
))
527 if (check_name(fname
,conn
))
528 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
530 ok
= set_filetime(conn
,fname
,mtime
);
533 set_bad_path_error(errno
, bad_path
);
534 END_PROFILE(SMBsetatr
);
535 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
538 outsize
= set_message(outbuf
,0,0,True
);
540 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
542 END_PROFILE(SMBsetatr
);
546 /****************************************************************************
548 ****************************************************************************/
550 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
553 SMB_BIG_UINT dfree
,dsize
,bsize
;
554 START_PROFILE(SMBdskattr
);
556 VFS_DISK_FREE(conn
,".",True
,&bsize
,&dfree
,&dsize
);
558 outsize
= set_message(outbuf
,5,0,True
);
560 if (Protocol
<= PROTOCOL_LANMAN2
) {
561 double total_space
, free_space
;
562 /* we need to scale this to a number that DOS6 can handle. We
563 use floating point so we can handle large drives on systems
564 that don't have 64 bit integers
566 we end up displaying a maximum of 2G to DOS systems
568 total_space
= dsize
* (double)bsize
;
569 free_space
= dfree
* (double)bsize
;
571 dsize
= (total_space
+63*512) / (64*512);
572 dfree
= (free_space
+63*512) / (64*512);
574 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
575 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
577 SSVAL(outbuf
,smb_vwv0
,dsize
);
578 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
579 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
580 SSVAL(outbuf
,smb_vwv3
,dfree
);
582 SSVAL(outbuf
,smb_vwv0
,dsize
);
583 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
584 SSVAL(outbuf
,smb_vwv2
,512);
585 SSVAL(outbuf
,smb_vwv3
,dfree
);
588 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
590 END_PROFILE(SMBdskattr
);
594 /****************************************************************************
596 Can be called from SMBsearch, SMBffirst or SMBfunique.
597 ****************************************************************************/
599 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
610 BOOL finished
= False
;
619 BOOL check_descend
= False
;
620 BOOL expect_close
= False
;
621 BOOL can_open
= True
;
622 BOOL bad_path
= False
;
623 START_PROFILE(SMBsearch
);
625 *mask
= *directory
= *fname
= 0;
627 /* If we were called as SMBffirst then we must expect close. */
628 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
631 outsize
= set_message(outbuf
,1,3,True
);
632 maxentries
= SVAL(inbuf
,smb_vwv0
);
633 dirtype
= SVAL(inbuf
,smb_vwv1
);
634 p
= smb_buf(inbuf
) + 1;
635 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
637 status_len
= SVAL(p
, 0);
640 /* dirtype &= ~aDIR; */
642 if (status_len
== 0) {
643 SMB_STRUCT_STAT sbuf
;
646 pstrcpy(directory
,path
);
648 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
651 if (!check_name(directory
,conn
))
654 p
= strrchr_m(dir2
,'/');
663 p
= strrchr_m(directory
,'/');
669 if (strlen(directory
) == 0)
670 pstrcpy(directory
,".");
671 memset((char *)status
,'\0',21);
672 SCVAL(status
,0,(dirtype
& 0x1F));
677 status_dirtype
= CVAL(status
,0) & 0x1F;
678 if (status_dirtype
!= (dirtype
& 0x1F))
679 dirtype
= status_dirtype
;
681 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
684 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
685 pstrcpy(mask
, dptr_wcard(dptr_num
));
689 p
= smb_buf(outbuf
) + 3;
692 if (status_len
== 0) {
693 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
696 set_bad_path_error(errno
, bad_path
);
697 END_PROFILE(SMBsearch
);
698 return (UNIXERROR(ERRDOS
,ERRnofids
));
700 END_PROFILE(SMBsearch
);
701 return ERROR_DOS(ERRDOS
,ERRnofids
);
703 dptr_set_wcard(dptr_num
, strdup(mask
));
704 dptr_set_attr(dptr_num
, dirtype
);
706 dirtype
= dptr_attr(dptr_num
);
709 DEBUG(4,("dptr_num is %d\n",dptr_num
));
712 if ((dirtype
&0x1F) == aVOLID
) {
714 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
715 dptr_fill(p
+12,dptr_num
);
716 if (dptr_zero(p
+12) && (status_len
==0))
720 p
+= DIR_STRUCT_SIZE
;
722 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
723 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
724 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
725 check_descend
= True
;
727 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
728 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
731 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
732 dptr_fill(p
+12,dptr_num
);
735 p
+= DIR_STRUCT_SIZE
;
744 if (numentries
== 0 || !ok
) {
745 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
746 SSVAL(outbuf
,smb_err
,ERRnofiles
);
747 dptr_close(&dptr_num
);
750 /* If we were called as SMBffirst with smb_search_id == NULL
751 and no entries were found then return error and close dirptr
754 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0) {
755 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
756 SSVAL(outbuf
,smb_err
,ERRnofiles
);
757 /* Also close the dptr - we know it's gone */
758 dptr_close(&dptr_num
);
761 /* If we were called as SMBfunique, then we can close the dirptr now ! */
762 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
763 dptr_close(&dptr_num
);
765 SSVAL(outbuf
,smb_vwv0
,numentries
);
766 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
767 SCVAL(smb_buf(outbuf
),0,5);
768 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
770 if (Protocol
>= PROTOCOL_NT1
)
771 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
773 outsize
+= DIR_STRUCT_SIZE
*numentries
;
774 smb_setlen(outbuf
,outsize
- 4);
776 if ((! *directory
) && dptr_path(dptr_num
))
777 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
779 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
780 smb_fn_name(CVAL(inbuf
,smb_com
)),
781 mask
, directory
, dirtype
, numentries
, maxentries
) );
783 END_PROFILE(SMBsearch
);
787 /****************************************************************************
788 Reply to a fclose (stop directory search).
789 ****************************************************************************/
791 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
800 START_PROFILE(SMBfclose
);
802 outsize
= set_message(outbuf
,1,0,True
);
803 p
= smb_buf(inbuf
) + 1;
804 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
806 status_len
= SVAL(p
,0);
809 if (status_len
== 0) {
810 END_PROFILE(SMBfclose
);
811 return ERROR_DOS(ERRSRV
,ERRsrverror
);
816 if(dptr_fetch(status
+12,&dptr_num
)) {
817 /* Close the dptr - we know it's gone */
818 dptr_close(&dptr_num
);
821 SSVAL(outbuf
,smb_vwv0
,0);
823 DEBUG(3,("search close\n"));
825 END_PROFILE(SMBfclose
);
829 /****************************************************************************
831 ****************************************************************************/
833 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
843 SMB_STRUCT_STAT sbuf
;
844 BOOL bad_path
= False
;
846 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
847 START_PROFILE(SMBopen
);
849 share_mode
= SVAL(inbuf
,smb_vwv0
);
851 srvstr_pull_buf(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), STR_TERMINATE
);
853 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
855 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
857 unixmode
= unix_mode(conn
,aARCH
,fname
);
859 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
860 unixmode
, oplock_request
,&rmode
,NULL
);
863 set_bad_path_error(errno
, bad_path
);
864 END_PROFILE(SMBopen
);
865 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
869 fmode
= dos_mode(conn
,fname
,&sbuf
);
870 mtime
= sbuf
.st_mtime
;
873 DEBUG(3,("attempt to open a directory %s\n",fname
));
874 close_file(fsp
,False
);
875 END_PROFILE(SMBopen
);
876 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
879 outsize
= set_message(outbuf
,7,0,True
);
880 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
881 SSVAL(outbuf
,smb_vwv1
,fmode
);
882 if(lp_dos_filetime_resolution(SNUM(conn
)) )
883 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
885 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
886 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
887 SSVAL(outbuf
,smb_vwv6
,rmode
);
889 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
890 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
892 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
893 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
894 END_PROFILE(SMBopen
);
898 /****************************************************************************
899 Reply to an open and X.
900 ****************************************************************************/
902 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
905 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
906 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
907 /* Breakout the oplock request bits so we can set the
908 reply bits separately. */
909 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
910 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
911 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
913 int open_flags
= SVAL(inbuf
,smb_vwv2
);
914 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
915 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
917 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
920 int fmode
=0,mtime
=0,rmode
=0;
921 SMB_STRUCT_STAT sbuf
;
923 BOOL bad_path
= False
;
925 START_PROFILE(SMBopenX
);
927 /* If it's an IPC, pass off the pipe handler. */
929 if (lp_nt_pipe_support()) {
930 END_PROFILE(SMBopenX
);
931 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
933 END_PROFILE(SMBopenX
);
934 return ERROR_DOS(ERRSRV
,ERRaccess
);
938 /* XXXX we need to handle passed times, sattr and flags */
939 srvstr_pull_buf(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), STR_TERMINATE
);
941 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
943 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
945 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
947 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
948 oplock_request
, &rmode
,&smb_action
);
951 set_bad_path_error(errno
, bad_path
);
952 END_PROFILE(SMBopenX
);
953 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
957 fmode
= dos_mode(conn
,fname
,&sbuf
);
958 mtime
= sbuf
.st_mtime
;
960 close_file(fsp
,False
);
961 END_PROFILE(SMBopenX
);
962 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
965 /* If the caller set the extended oplock request bit
966 and we granted one (by whatever means) - set the
967 correct bit for extended oplock reply.
970 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
971 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
973 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
974 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
976 /* If the caller set the core oplock request bit
977 and we granted one (by whatever means) - set the
978 correct bit for core oplock reply.
981 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
982 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
984 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
985 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
987 set_message(outbuf
,15,0,True
);
988 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
989 SSVAL(outbuf
,smb_vwv3
,fmode
);
990 if(lp_dos_filetime_resolution(SNUM(conn
)) )
991 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
993 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
994 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
995 SSVAL(outbuf
,smb_vwv8
,rmode
);
996 SSVAL(outbuf
,smb_vwv11
,smb_action
);
998 END_PROFILE(SMBopenX
);
999 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1002 /****************************************************************************
1003 Reply to a SMBulogoffX.
1004 ****************************************************************************/
1006 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1008 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1009 user_struct
*vuser
= get_valid_user_struct(vuid
);
1010 START_PROFILE(SMBulogoffX
);
1013 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1015 /* in user level security we are supposed to close any files
1016 open by this user */
1017 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
))
1018 file_close_user(vuid
);
1020 invalidate_vuid(vuid
);
1022 set_message(outbuf
,2,0,True
);
1024 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1026 END_PROFILE(SMBulogoffX
);
1027 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1030 /****************************************************************************
1031 Reply to a mknew or a create.
1032 ****************************************************************************/
1034 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1042 BOOL bad_path
= False
;
1044 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1045 SMB_STRUCT_STAT sbuf
;
1046 START_PROFILE(SMBcreate
);
1048 com
= SVAL(inbuf
,smb_com
);
1050 createmode
= SVAL(inbuf
,smb_vwv0
);
1051 srvstr_pull_buf(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), STR_TERMINATE
);
1053 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1055 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1057 if (createmode
& aVOLID
)
1058 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1060 unixmode
= unix_mode(conn
,createmode
,fname
);
1062 if(com
== SMBmknew
) {
1063 /* We should fail if file exists. */
1064 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1066 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1067 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1070 /* Open file in dos compatibility share mode. */
1071 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1072 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1075 set_bad_path_error(errno
, bad_path
);
1076 END_PROFILE(SMBcreate
);
1077 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1080 outsize
= set_message(outbuf
,1,0,True
);
1081 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1083 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1084 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1086 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1087 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1089 DEBUG( 2, ( "new file %s\n", fname
) );
1090 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1092 END_PROFILE(SMBcreate
);
1096 /****************************************************************************
1097 Reply to a create temporary file.
1098 ****************************************************************************/
1100 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1106 BOOL bad_path
= False
;
1108 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1110 SMB_STRUCT_STAT sbuf
;
1113 START_PROFILE(SMBctemp
);
1115 createmode
= SVAL(inbuf
,smb_vwv0
);
1116 srvstr_pull_buf(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), STR_TERMINATE
);
1117 pstrcat(fname
,"\\TMXXXXXX");
1119 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1121 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1123 unixmode
= unix_mode(conn
,createmode
,fname
);
1125 tmpfd
= smb_mkstemp(fname
);
1127 END_PROFILE(SMBctemp
);
1128 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1131 VFS_STAT(conn
,fname
,&sbuf
);
1133 /* Open file in dos compatibility share mode. */
1134 /* We should fail if file does not exist. */
1135 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1136 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1137 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1138 unixmode
, oplock_request
, NULL
, NULL
);
1140 /* close fd from smb_mkstemp() */
1144 set_bad_path_error(errno
, bad_path
);
1145 END_PROFILE(SMBctemp
);
1146 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1149 outsize
= set_message(outbuf
,1,0,True
);
1150 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1152 /* the returned filename is relative to the directory */
1153 s
= strrchr_m(fname
, '/');
1159 p
= smb_buf(outbuf
);
1160 SSVALS(p
, 0, -1); /* what is this? not in spec */
1161 SSVAL(p
, 2, strlen(s
));
1163 p
+= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
);
1164 outsize
= set_message_end(outbuf
, p
);
1166 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1167 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1169 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1170 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1172 DEBUG( 2, ( "created temp file %s\n", fname
) );
1173 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1174 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1176 END_PROFILE(SMBctemp
);
1180 /*******************************************************************
1181 Check if a user is allowed to rename a file.
1182 ********************************************************************/
1184 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1190 if (!CAN_WRITE(conn
))
1191 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1193 if (S_ISDIR(pst
->st_mode
))
1194 return NT_STATUS_OK
;
1196 /* We need a better way to return NT status codes from open... */
1200 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1201 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1204 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1205 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1206 ret
= NT_STATUS_SHARING_VIOLATION
;
1211 close_file(fsp
,False
);
1212 return NT_STATUS_OK
;
1215 /*******************************************************************
1216 Check if a user is allowed to delete a file.
1217 ********************************************************************/
1219 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1221 SMB_STRUCT_STAT sbuf
;
1227 if (!CAN_WRITE(conn
))
1228 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1230 if (VFS_LSTAT(conn
,fname
,&sbuf
) != 0)
1231 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1233 fmode
= dos_mode(conn
,fname
,&sbuf
);
1235 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1236 if (!lp_delete_readonly(SNUM(conn
))) {
1238 return NT_STATUS_CANNOT_DELETE
;
1240 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1241 return NT_STATUS_CANNOT_DELETE
;
1243 /* We need a better way to return NT status codes from open... */
1247 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1248 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1251 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1252 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus
))
1253 ret
= unix_ERR_ntstatus
;
1254 else if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1255 ret
= NT_STATUS_SHARING_VIOLATION
;
1258 unix_ERR_ntstatus
= NT_STATUS_OK
;
1261 close_file(fsp
,False
);
1262 return NT_STATUS_OK
;
1265 /****************************************************************************
1266 The guts of the unlink command, split out so it may be called by the NT SMB
1268 ****************************************************************************/
1270 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1276 NTSTATUS error
= NT_STATUS_OK
;
1278 BOOL bad_path
= False
;
1280 SMB_STRUCT_STAT sbuf
;
1282 *directory
= *mask
= 0;
1284 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1286 p
= strrchr_m(name
,'/');
1288 pstrcpy(directory
,".");
1292 pstrcpy(directory
,name
);
1297 * We should only check the mangled cache
1298 * here if unix_convert failed. This means
1299 * that the path in 'mask' doesn't exist
1300 * on the file system and so we need to look
1301 * for a possible mangle. This patch from
1302 * Tine Smukavec <valentin.smukavec@hermes.si>.
1305 if (!rc
&& mangle_is_mangled(mask
))
1306 mangle_check_cache( mask
);
1308 has_wild
= ms_has_wild(mask
);
1311 pstrcat(directory
,"/");
1312 pstrcat(directory
,mask
);
1313 error
= can_delete(directory
,conn
,dirtype
);
1314 if (!NT_STATUS_IS_OK(error
)) return error
;
1316 if (VFS_UNLINK(conn
,directory
) == 0) {
1320 void *dirptr
= NULL
;
1323 if (check_name(directory
,conn
))
1324 dirptr
= OpenDir(conn
, directory
, True
);
1326 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1327 the pattern matches against the long name, otherwise the short name
1328 We don't implement this yet XXXX
1332 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1334 if (strequal(mask
,"????????.???"))
1337 while ((dname
= ReadDirName(dirptr
))) {
1339 pstrcpy(fname
,dname
);
1341 if(!mask_match(fname
, mask
, case_sensitive
)) continue;
1343 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1344 error
= can_delete(fname
,conn
,dirtype
);
1345 if (!NT_STATUS_IS_OK(error
)) continue;
1346 if (VFS_UNLINK(conn
,fname
) == 0) count
++;
1347 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1353 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1354 error
= map_nt_error_from_unix(errno
);
1360 /****************************************************************************
1362 ****************************************************************************/
1364 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1371 START_PROFILE(SMBunlink
);
1373 dirtype
= SVAL(inbuf
,smb_vwv0
);
1375 srvstr_pull_buf(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), STR_TERMINATE
);
1377 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1379 DEBUG(3,("reply_unlink : %s\n",name
));
1381 status
= unlink_internals(conn
, dirtype
, name
);
1382 if (!NT_STATUS_IS_OK(status
)) return ERROR_NT(status
);
1385 * Win2k needs a changenotify request response before it will
1386 * update after a rename..
1388 process_pending_change_notify_queue((time_t)0);
1390 outsize
= set_message(outbuf
,0,0,True
);
1392 END_PROFILE(SMBunlink
);
1396 /****************************************************************************
1398 ****************************************************************************/
1400 void fail_readraw(void)
1403 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1405 exit_server(errstr
);
1408 /****************************************************************************
1409 Use sendfile in readbraw.
1410 ****************************************************************************/
1412 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
1413 ssize_t mincount
, char *outbuf
)
1417 #if defined(WITH_SENDFILE)
1419 * We can only use sendfile on a non-chained packet and on a file
1420 * that is exclusively oplocked. reply_readbraw has already checked the length.
1423 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
1424 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
1427 _smb_setlen(outbuf
,nread
);
1428 header
.data
= outbuf
;
1432 if ( VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
1434 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1435 * return ENOSYS then pretend we just got a normal read.
1437 if (errno
== ENOSYS
)
1440 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1441 fsp
->fsp_name
, strerror(errno
) ));
1442 exit_server("send_file_readbraw sendfile failed");
1451 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
1456 _smb_setlen(outbuf
,ret
);
1457 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
1461 /****************************************************************************
1462 Reply to a readbraw (core+ protocol).
1463 ****************************************************************************/
1465 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1467 extern struct current_user current_user
;
1468 ssize_t maxcount
,mincount
;
1471 char *header
= outbuf
;
1473 START_PROFILE(SMBreadbraw
);
1476 * Special check if an oplock break has been issued
1477 * and the readraw request croses on the wire, we must
1478 * return a zero length response here.
1481 if(global_oplock_break
) {
1482 _smb_setlen(header
,0);
1483 if (write_data(smbd_server_fd(),header
,4) != 4)
1485 DEBUG(5,("readbraw - oplock break finished\n"));
1486 END_PROFILE(SMBreadbraw
);
1490 fsp
= file_fsp(inbuf
,smb_vwv0
);
1492 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1494 * fsp could be NULL here so use the value from the packet. JRA.
1496 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1497 _smb_setlen(header
,0);
1498 if (write_data(smbd_server_fd(),header
,4) != 4)
1500 END_PROFILE(SMBreadbraw
);
1504 CHECK_FSP(fsp
,conn
);
1506 flush_write_cache(fsp
, READRAW_FLUSH
);
1508 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
1509 if(CVAL(inbuf
,smb_wct
) == 10) {
1511 * This is a large offset (64 bit) read.
1513 #ifdef LARGE_SMB_OFF_T
1515 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1517 #else /* !LARGE_SMB_OFF_T */
1520 * Ensure we haven't been sent a >32 bit offset.
1523 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1524 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1525 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1526 _smb_setlen(header
,0);
1527 if (write_data(smbd_server_fd(),header
,4) != 4)
1529 END_PROFILE(SMBreadbraw
);
1533 #endif /* LARGE_SMB_OFF_T */
1536 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1537 _smb_setlen(header
,0);
1538 if (write_data(smbd_server_fd(),header
,4) != 4)
1540 END_PROFILE(SMBreadbraw
);
1544 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1545 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1547 /* ensure we don't overrun the packet size */
1548 maxcount
= MIN(65535,maxcount
);
1549 maxcount
= MAX(mincount
,maxcount
);
1551 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1552 SMB_OFF_T size
= fsp
->size
;
1553 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1555 if (size
< sizeneeded
) {
1557 if (VFS_FSTAT(fsp
,fsp
->fd
,&st
) == 0)
1559 if (!fsp
->can_write
)
1563 if (startpos
>= size
)
1566 nread
= MIN(maxcount
,(size
- startpos
));
1569 if (nread
< mincount
)
1572 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1573 (int)maxcount
, (int)mincount
, (int)nread
) );
1575 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
1577 DEBUG(5,("readbraw finished\n"));
1578 END_PROFILE(SMBreadbraw
);
1582 /****************************************************************************
1583 Reply to a lockread (core+ protocol).
1584 ****************************************************************************/
1586 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1594 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1595 START_PROFILE(SMBlockread
);
1597 CHECK_FSP(fsp
,conn
);
1600 release_level_2_oplocks_on_change(fsp
);
1602 numtoread
= SVAL(inbuf
,smb_vwv1
);
1603 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1605 outsize
= set_message(outbuf
,5,3,True
);
1606 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1607 data
= smb_buf(outbuf
) + 3;
1610 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1611 * protocol request that predates the read/write lock concept.
1612 * Thus instead of asking for a read lock here we need to ask
1613 * for a write lock. JRA.
1616 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1617 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
);
1619 if (NT_STATUS_V(status
)) {
1620 if (lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
1622 * A blocking lock was requested. Package up
1623 * this smb into a queued request and push it
1624 * onto the blocking lock queue.
1626 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)startpos
,
1627 (SMB_BIG_UINT
)numtoread
)) {
1628 END_PROFILE(SMBlockread
);
1632 END_PROFILE(SMBlockread
);
1633 return ERROR_NT(status
);
1636 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1639 END_PROFILE(SMBlockread
);
1640 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1644 SSVAL(outbuf
,smb_vwv0
,nread
);
1645 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1646 SSVAL(smb_buf(outbuf
),1,nread
);
1648 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1649 fsp
->fnum
, (int)numtoread
, (int)nread
));
1651 END_PROFILE(SMBlockread
);
1655 /****************************************************************************
1657 ****************************************************************************/
1659 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1666 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1667 START_PROFILE(SMBread
);
1669 CHECK_FSP(fsp
,conn
);
1672 numtoread
= SVAL(inbuf
,smb_vwv1
);
1673 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1675 outsize
= set_message(outbuf
,5,3,True
);
1676 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1677 data
= smb_buf(outbuf
) + 3;
1679 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1680 END_PROFILE(SMBread
);
1681 return ERROR_DOS(ERRDOS
,ERRlock
);
1685 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1688 END_PROFILE(SMBread
);
1689 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1693 SSVAL(outbuf
,smb_vwv0
,nread
);
1694 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1695 SCVAL(smb_buf(outbuf
),0,1);
1696 SSVAL(smb_buf(outbuf
),1,nread
);
1698 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1699 fsp
->fnum
, (int)numtoread
, (int)nread
) );
1701 END_PROFILE(SMBread
);
1705 /****************************************************************************
1706 Reply to a read and X - possibly using sendfile.
1707 ****************************************************************************/
1709 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
1710 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
1713 char *data
= smb_buf(outbuf
);
1715 #if defined(WITH_SENDFILE)
1717 * We can only use sendfile on a non-chained packet and on a file
1718 * that is exclusively oplocked.
1721 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
1722 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
1723 SMB_STRUCT_STAT sbuf
;
1726 if(VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1)
1727 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1729 if (startpos
> sbuf
.st_size
)
1732 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
1733 smb_maxcnt
= (sbuf
.st_size
- startpos
);
1735 if (smb_maxcnt
== 0)
1739 * Set up the packet header before send. We
1740 * assume here the sendfile will work (get the
1741 * correct amount of data).
1744 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
1745 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1746 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
1747 SCVAL(outbuf
,smb_vwv0
,0xFF);
1748 set_message(outbuf
,12,smb_maxcnt
,False
);
1749 header
.data
= outbuf
;
1750 header
.length
= data
- outbuf
;
1753 if ( VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
1755 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1756 * return ENOSYS then pretend we just got a normal read.
1758 if (errno
== ENOSYS
)
1761 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1762 fsp
->fsp_name
, strerror(errno
) ));
1763 exit_server("send_file_readX sendfile failed");
1766 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1767 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
1775 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
1778 END_PROFILE(SMBreadX
);
1779 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1782 SSVAL(outbuf
,smb_vwv5
,nread
);
1783 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1784 SSVAL(smb_buf(outbuf
),-2,nread
);
1786 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1787 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
1792 /****************************************************************************
1793 Reply to a read and X.
1794 ****************************************************************************/
1796 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1798 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
1799 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
1801 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1803 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1806 START_PROFILE(SMBreadX
);
1808 /* If it's an IPC, pass off the pipe handler. */
1810 END_PROFILE(SMBreadX
);
1811 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
1814 CHECK_FSP(fsp
,conn
);
1817 set_message(outbuf
,12,0,True
);
1819 if(CVAL(inbuf
,smb_wct
) == 12) {
1820 #ifdef LARGE_SMB_OFF_T
1822 * This is a large offset (64 bit) read.
1824 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
1826 #else /* !LARGE_SMB_OFF_T */
1829 * Ensure we haven't been sent a >32 bit offset.
1832 if(IVAL(inbuf
,smb_vwv10
) != 0) {
1833 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1834 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
1835 END_PROFILE(SMBreadX
);
1836 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
1839 #endif /* LARGE_SMB_OFF_T */
1843 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1844 END_PROFILE(SMBreadX
);
1845 return ERROR_DOS(ERRDOS
,ERRlock
);
1848 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
1850 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
1852 END_PROFILE(SMBreadX
);
1856 /****************************************************************************
1857 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1858 ****************************************************************************/
1860 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1863 ssize_t total_written
=0;
1864 size_t numtowrite
=0;
1869 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1871 START_PROFILE(SMBwritebraw
);
1873 CHECK_FSP(fsp
,conn
);
1876 tcount
= IVAL(inbuf
,smb_vwv1
);
1877 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
1878 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1880 /* We have to deal with slightly different formats depending
1881 on whether we are using the core+ or lanman1.0 protocol */
1883 if(Protocol
<= PROTOCOL_COREPLUS
) {
1884 numtowrite
= SVAL(smb_buf(inbuf
),-2);
1885 data
= smb_buf(inbuf
);
1887 numtowrite
= SVAL(inbuf
,smb_vwv10
);
1888 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
1891 /* force the error type */
1892 SCVAL(inbuf
,smb_com
,SMBwritec
);
1893 SCVAL(outbuf
,smb_com
,SMBwritec
);
1895 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
1896 END_PROFILE(SMBwritebraw
);
1897 return(ERROR_DOS(ERRDOS
,ERRlock
));
1901 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
1903 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1904 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
1906 if (nwritten
< (ssize_t
)numtowrite
) {
1907 END_PROFILE(SMBwritebraw
);
1908 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
1911 total_written
= nwritten
;
1913 /* Return a message to the redirector to tell it to send more bytes */
1914 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
1915 SSVALS(outbuf
,smb_vwv0
,-1);
1916 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
1917 if (!send_smb(smbd_server_fd(),outbuf
))
1918 exit_server("reply_writebraw: send_smb failed.");
1920 /* Now read the raw data into the buffer and write it */
1921 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
1922 exit_server("secondary writebraw failed");
1925 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1926 numtowrite
= smb_len(inbuf
);
1928 /* Set up outbuf to return the correct return */
1929 outsize
= set_message(outbuf
,1,0,True
);
1930 SCVAL(outbuf
,smb_com
,SMBwritec
);
1931 SSVAL(outbuf
,smb_vwv0
,total_written
);
1933 if (numtowrite
!= 0) {
1935 if (numtowrite
> BUFFER_SIZE
) {
1936 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1937 (unsigned int)numtowrite
));
1938 exit_server("secondary writebraw failed");
1941 if (tcount
> nwritten
+numtowrite
) {
1942 DEBUG(3,("Client overestimated the write %d %d %d\n",
1943 (int)tcount
,(int)nwritten
,(int)numtowrite
));
1946 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
1947 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1949 exit_server("secondary writebraw failed");
1952 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
1954 if (nwritten
< (ssize_t
)numtowrite
) {
1955 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
1956 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1960 total_written
+= nwritten
;
1963 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
1964 sync_file(conn
,fsp
);
1966 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1967 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
1969 /* we won't return a status if write through is not selected - this follows what WfWg does */
1970 END_PROFILE(SMBwritebraw
);
1971 if (!write_through
&& total_written
==tcount
) {
1973 #if RABBIT_PELLET_FIX
1975 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1976 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1978 if (!send_keepalive(smbd_server_fd()))
1979 exit_server("reply_writebraw: send of keepalive failed");
1987 /****************************************************************************
1988 Reply to a writeunlock (core+).
1989 ****************************************************************************/
1991 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
1992 int size
, int dum_buffsize
)
1994 ssize_t nwritten
= -1;
1999 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2001 START_PROFILE(SMBwriteunlock
);
2003 CHECK_FSP(fsp
,conn
);
2006 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2007 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2008 data
= smb_buf(inbuf
) + 3;
2010 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2011 WRITE_LOCK
,False
)) {
2012 END_PROFILE(SMBwriteunlock
);
2013 return ERROR_DOS(ERRDOS
,ERRlock
);
2016 /* The special X/Open SMB protocol handling of
2017 zero length writes is *NOT* done for
2022 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2024 if (lp_syncalways(SNUM(conn
)))
2025 sync_file(conn
,fsp
);
2027 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2028 END_PROFILE(SMBwriteunlock
);
2029 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2032 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2033 (SMB_BIG_UINT
)startpos
);
2034 if (NT_STATUS_V(status
)) {
2035 END_PROFILE(SMBwriteunlock
);
2036 return ERROR_NT(status
);
2039 outsize
= set_message(outbuf
,1,0,True
);
2041 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2043 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2044 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2046 END_PROFILE(SMBwriteunlock
);
2050 /****************************************************************************
2052 ****************************************************************************/
2054 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2057 ssize_t nwritten
= -1;
2060 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2062 START_PROFILE(SMBwrite
);
2064 /* If it's an IPC, pass off the pipe handler. */
2066 END_PROFILE(SMBwrite
);
2067 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2070 CHECK_FSP(fsp
,conn
);
2073 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2074 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2075 data
= smb_buf(inbuf
) + 3;
2077 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2078 END_PROFILE(SMBwrite
);
2079 return ERROR_DOS(ERRDOS
,ERRlock
);
2083 * X/Open SMB protocol says that if smb_vwv1 is
2084 * zero then the file size should be extended or
2085 * truncated to the size given in smb_vwv[2-3].
2088 if(numtowrite
== 0) {
2090 * This is actually an allocate call, and set EOF. JRA.
2092 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2094 END_PROFILE(SMBwrite
);
2095 return ERROR_NT(NT_STATUS_DISK_FULL
);
2097 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2099 END_PROFILE(SMBwrite
);
2100 return ERROR_NT(NT_STATUS_DISK_FULL
);
2103 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2105 if (lp_syncalways(SNUM(conn
)))
2106 sync_file(conn
,fsp
);
2108 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2109 END_PROFILE(SMBwrite
);
2110 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2113 outsize
= set_message(outbuf
,1,0,True
);
2115 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2117 if (nwritten
< (ssize_t
)numtowrite
) {
2118 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2119 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2122 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2124 END_PROFILE(SMBwrite
);
2128 /****************************************************************************
2129 Reply to a write and X.
2130 ****************************************************************************/
2132 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2134 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2135 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2136 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2137 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2138 ssize_t nwritten
= -1;
2139 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2140 unsigned int smblen
= smb_len(inbuf
);
2142 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2143 START_PROFILE(SMBwriteX
);
2145 /* If it's an IPC, pass off the pipe handler. */
2147 END_PROFILE(SMBwriteX
);
2148 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2151 CHECK_FSP(fsp
,conn
);
2154 /* Deal with possible LARGE_WRITEX */
2156 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2158 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2159 END_PROFILE(SMBwriteX
);
2160 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2163 data
= smb_base(inbuf
) + smb_doff
;
2165 if(CVAL(inbuf
,smb_wct
) == 14) {
2166 #ifdef LARGE_SMB_OFF_T
2168 * This is a large offset (64 bit) write.
2170 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2172 #else /* !LARGE_SMB_OFF_T */
2175 * Ensure we haven't been sent a >32 bit offset.
2178 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2179 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2180 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2181 END_PROFILE(SMBwriteX
);
2182 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2185 #endif /* LARGE_SMB_OFF_T */
2188 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2189 END_PROFILE(SMBwriteX
);
2190 return ERROR_DOS(ERRDOS
,ERRlock
);
2193 /* X/Open SMB protocol says that, unlike SMBwrite
2194 if the length is zero then NO truncation is
2195 done, just a write of zero. To truncate a file,
2201 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2203 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2204 END_PROFILE(SMBwriteX
);
2205 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2208 set_message(outbuf
,6,0,True
);
2210 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2212 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2214 if (nwritten
< (ssize_t
)numtowrite
) {
2215 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2216 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2219 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2220 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2222 if (lp_syncalways(SNUM(conn
)) || write_through
)
2223 sync_file(conn
,fsp
);
2225 END_PROFILE(SMBwriteX
);
2226 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2229 /****************************************************************************
2231 ****************************************************************************/
2233 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2239 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2240 START_PROFILE(SMBlseek
);
2242 CHECK_FSP(fsp
,conn
);
2244 flush_write_cache(fsp
, SEEK_FLUSH
);
2246 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2247 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2248 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
2265 if((res
= VFS_LSEEK(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2267 * Check for the special case where a seek before the start
2268 * of the file sets the offset to zero. Added in the CIFS spec,
2272 if(errno
== EINVAL
) {
2273 SMB_OFF_T current_pos
= startpos
;
2275 if(umode
== SEEK_CUR
) {
2277 if((current_pos
= VFS_LSEEK(fsp
,fsp
->fd
,0,SEEK_CUR
)) == -1) {
2278 END_PROFILE(SMBlseek
);
2279 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2282 current_pos
+= startpos
;
2284 } else if (umode
== SEEK_END
) {
2286 SMB_STRUCT_STAT sbuf
;
2288 if(VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1) {
2289 END_PROFILE(SMBlseek
);
2290 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2293 current_pos
+= sbuf
.st_size
;
2297 res
= VFS_LSEEK(fsp
,fsp
->fd
,0,SEEK_SET
);
2301 END_PROFILE(SMBlseek
);
2302 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2308 outsize
= set_message(outbuf
,2,0,True
);
2309 SIVAL(outbuf
,smb_vwv0
,res
);
2311 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2312 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2314 END_PROFILE(SMBlseek
);
2318 /****************************************************************************
2320 ****************************************************************************/
2322 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2324 int outsize
= set_message(outbuf
,0,0,True
);
2325 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2326 START_PROFILE(SMBflush
);
2328 CHECK_FSP(fsp
,conn
);
2331 file_sync_all(conn
);
2333 sync_file(conn
,fsp
);
2336 DEBUG(3,("flush\n"));
2337 END_PROFILE(SMBflush
);
2341 /****************************************************************************
2343 ****************************************************************************/
2345 int reply_exit(connection_struct
*conn
,
2346 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2349 START_PROFILE(SMBexit
);
2350 outsize
= set_message(outbuf
,0,0,True
);
2352 DEBUG(3,("exit\n"));
2354 END_PROFILE(SMBexit
);
2358 /****************************************************************************
2359 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2360 ****************************************************************************/
2362 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2365 extern struct current_user current_user
;
2368 int32 eclass
= 0, err
= 0;
2369 files_struct
*fsp
= NULL
;
2370 START_PROFILE(SMBclose
);
2372 outsize
= set_message(outbuf
,0,0,True
);
2374 /* If it's an IPC, pass off to the pipe handler. */
2376 END_PROFILE(SMBclose
);
2377 return reply_pipe_close(conn
, inbuf
,outbuf
);
2380 fsp
= file_fsp(inbuf
,smb_vwv0
);
2383 * We can only use CHECK_FSP if we know it's not a directory.
2386 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
2387 END_PROFILE(SMBclose
);
2388 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2391 if(fsp
->is_directory
) {
2393 * Special case - close NT SMB directory handle.
2395 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2396 close_file(fsp
,True
);
2399 * Close ordinary file.
2404 /* Save the name for time set in close. */
2405 pstrcpy( file_name
, fsp
->fsp_name
);
2407 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2409 conn
->num_files_open
));
2412 * close_file() returns the unix errno if an error
2413 * was detected on close - normally this is due to
2414 * a disk full error. If not then it was probably an I/O error.
2417 if((close_err
= close_file(fsp
,True
)) != 0) {
2419 END_PROFILE(SMBclose
);
2420 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2424 * Now take care of any time sent in the close.
2427 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2429 /* try and set the date */
2430 set_filetime(conn
, file_name
, mtime
);
2434 /* We have a cached error */
2436 END_PROFILE(SMBclose
);
2437 return ERROR_DOS(eclass
,err
);
2440 END_PROFILE(SMBclose
);
2444 /****************************************************************************
2445 Reply to a writeclose (Core+ protocol).
2446 ****************************************************************************/
2448 int reply_writeclose(connection_struct
*conn
,
2449 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2452 ssize_t nwritten
= -1;
2458 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2459 START_PROFILE(SMBwriteclose
);
2461 CHECK_FSP(fsp
,conn
);
2464 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2465 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2466 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2467 data
= smb_buf(inbuf
) + 1;
2469 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2470 END_PROFILE(SMBwriteclose
);
2471 return ERROR_DOS(ERRDOS
,ERRlock
);
2474 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2476 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2478 close_err
= close_file(fsp
,True
);
2480 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2481 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2482 conn
->num_files_open
));
2484 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2485 END_PROFILE(SMBwriteclose
);
2486 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2489 if(close_err
!= 0) {
2491 END_PROFILE(SMBwriteclose
);
2492 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2495 outsize
= set_message(outbuf
,1,0,True
);
2497 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2498 END_PROFILE(SMBwriteclose
);
2502 /****************************************************************************
2504 ****************************************************************************/
2506 int reply_lock(connection_struct
*conn
,
2507 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2509 int outsize
= set_message(outbuf
,0,0,True
);
2510 SMB_BIG_UINT count
,offset
;
2512 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2513 START_PROFILE(SMBlock
);
2515 CHECK_FSP(fsp
,conn
);
2517 release_level_2_oplocks_on_change(fsp
);
2519 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2520 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2522 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2523 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2525 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
);
2526 if (NT_STATUS_V(status
)) {
2527 if (lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
2529 * A blocking lock was requested. Package up
2530 * this smb into a queued request and push it
2531 * onto the blocking lock queue.
2533 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), offset
, count
)) {
2534 END_PROFILE(SMBlock
);
2538 END_PROFILE(SMBlock
);
2539 return ERROR_NT(status
);
2542 END_PROFILE(SMBlock
);
2546 /****************************************************************************
2548 ****************************************************************************/
2550 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2553 int outsize
= set_message(outbuf
,0,0,True
);
2554 SMB_BIG_UINT count
,offset
;
2556 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2557 START_PROFILE(SMBunlock
);
2559 CHECK_FSP(fsp
,conn
);
2561 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2562 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2564 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2565 if (NT_STATUS_V(status
)) {
2566 END_PROFILE(SMBunlock
);
2567 return ERROR_NT(status
);
2570 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2571 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2573 END_PROFILE(SMBunlock
);
2577 /****************************************************************************
2579 ****************************************************************************/
2581 int reply_tdis(connection_struct
*conn
,
2582 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2584 int outsize
= set_message(outbuf
,0,0,True
);
2586 START_PROFILE(SMBtdis
);
2588 vuid
= SVAL(inbuf
,smb_uid
);
2591 DEBUG(4,("Invalid connection in tdis\n"));
2592 END_PROFILE(SMBtdis
);
2593 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2598 close_cnum(conn
,vuid
);
2600 END_PROFILE(SMBtdis
);
2604 /****************************************************************************
2606 ****************************************************************************/
2608 int reply_echo(connection_struct
*conn
,
2609 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2611 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2613 unsigned int data_len
= smb_buflen(inbuf
);
2614 int outsize
= set_message(outbuf
,1,data_len
,True
);
2615 START_PROFILE(SMBecho
);
2617 data_len
= MIN(data_len
, (sizeof(inbuf
)-(smb_buf(inbuf
)-inbuf
)));
2619 /* copy any incoming data back out */
2621 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2623 if (smb_reverb
> 100) {
2624 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2628 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2629 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2631 smb_setlen(outbuf
,outsize
- 4);
2633 if (!send_smb(smbd_server_fd(),outbuf
))
2634 exit_server("reply_echo: send_smb failed.");
2637 DEBUG(3,("echo %d times\n", smb_reverb
));
2641 END_PROFILE(SMBecho
);
2645 /****************************************************************************
2646 Reply to a printopen.
2647 ****************************************************************************/
2649 int reply_printopen(connection_struct
*conn
,
2650 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2654 START_PROFILE(SMBsplopen
);
2656 if (!CAN_PRINT(conn
)) {
2657 END_PROFILE(SMBsplopen
);
2658 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2661 /* Open for exclusive use, write only. */
2662 fsp
= print_fsp_open(conn
, NULL
);
2665 END_PROFILE(SMBsplopen
);
2666 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2669 outsize
= set_message(outbuf
,1,0,True
);
2670 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2672 DEBUG(3,("openprint fd=%d fnum=%d\n",
2673 fsp
->fd
, fsp
->fnum
));
2675 END_PROFILE(SMBsplopen
);
2679 /****************************************************************************
2680 Reply to a printclose.
2681 ****************************************************************************/
2683 int reply_printclose(connection_struct
*conn
,
2684 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2686 int outsize
= set_message(outbuf
,0,0,True
);
2687 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2689 START_PROFILE(SMBsplclose
);
2691 CHECK_FSP(fsp
,conn
);
2693 if (!CAN_PRINT(conn
)) {
2694 END_PROFILE(SMBsplclose
);
2695 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2698 DEBUG(3,("printclose fd=%d fnum=%d\n",
2699 fsp
->fd
,fsp
->fnum
));
2701 close_err
= close_file(fsp
,True
);
2703 if(close_err
!= 0) {
2705 END_PROFILE(SMBsplclose
);
2706 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2709 END_PROFILE(SMBsplclose
);
2713 /****************************************************************************
2714 Reply to a printqueue.
2715 ****************************************************************************/
2717 int reply_printqueue(connection_struct
*conn
,
2718 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2720 int outsize
= set_message(outbuf
,2,3,True
);
2721 int max_count
= SVAL(inbuf
,smb_vwv0
);
2722 int start_index
= SVAL(inbuf
,smb_vwv1
);
2723 START_PROFILE(SMBsplretq
);
2725 /* we used to allow the client to get the cnum wrong, but that
2726 is really quite gross and only worked when there was only
2727 one printer - I think we should now only accept it if they
2728 get it right (tridge) */
2729 if (!CAN_PRINT(conn
)) {
2730 END_PROFILE(SMBsplretq
);
2731 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2734 SSVAL(outbuf
,smb_vwv0
,0);
2735 SSVAL(outbuf
,smb_vwv1
,0);
2736 SCVAL(smb_buf(outbuf
),0,1);
2737 SSVAL(smb_buf(outbuf
),1,0);
2739 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2740 start_index
, max_count
));
2743 print_queue_struct
*queue
= NULL
;
2744 print_status_struct status
;
2745 char *p
= smb_buf(outbuf
) + 3;
2746 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
2747 int num_to_get
= ABS(max_count
);
2748 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2754 num_to_get
= MIN(num_to_get
,count
-first
);
2757 for (i
=first
;i
<first
+num_to_get
;i
++) {
2758 put_dos_date2(p
,0,queue
[i
].time
);
2759 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
2760 SSVAL(p
,5, queue
[i
].job
);
2761 SIVAL(p
,7,queue
[i
].size
);
2763 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
2768 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2769 SSVAL(outbuf
,smb_vwv0
,count
);
2770 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2771 SCVAL(smb_buf(outbuf
),0,1);
2772 SSVAL(smb_buf(outbuf
),1,28*count
);
2777 DEBUG(3,("%d entries returned in queue\n",count
));
2780 END_PROFILE(SMBsplretq
);
2784 /****************************************************************************
2785 Reply to a printwrite.
2786 ****************************************************************************/
2788 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2791 int outsize
= set_message(outbuf
,0,0,True
);
2793 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2795 START_PROFILE(SMBsplwr
);
2797 if (!CAN_PRINT(conn
)) {
2798 END_PROFILE(SMBsplwr
);
2799 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2802 CHECK_FSP(fsp
,conn
);
2805 numtowrite
= SVAL(smb_buf(inbuf
),1);
2806 data
= smb_buf(inbuf
) + 3;
2808 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
2809 END_PROFILE(SMBsplwr
);
2810 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2813 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
2815 END_PROFILE(SMBsplwr
);
2819 /****************************************************************************
2820 The guts of the mkdir command, split out so it may be called by the NT SMB
2822 ****************************************************************************/
2824 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
2826 BOOL bad_path
= False
;
2827 SMB_STRUCT_STAT sbuf
;
2830 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
2832 if (check_name(directory
, conn
))
2833 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
2836 NTSTATUS nterr
= set_bad_path_error(errno
, bad_path
);
2837 if (!NT_STATUS_IS_OK(nterr
))
2839 return map_nt_error_from_unix(errno
);
2842 return NT_STATUS_OK
;
2845 /****************************************************************************
2847 ****************************************************************************/
2849 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2854 START_PROFILE(SMBmkdir
);
2856 srvstr_pull_buf(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), STR_TERMINATE
);
2858 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
2860 status
= mkdir_internal(conn
, directory
);
2861 if (!NT_STATUS_IS_OK(status
))
2862 return ERROR_NT(status
);
2864 outsize
= set_message(outbuf
,0,0,True
);
2866 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
2868 END_PROFILE(SMBmkdir
);
2872 /****************************************************************************
2873 Static function used by reply_rmdir to delete an entire directory
2874 tree recursively. Return False on ok, True on fail.
2875 ****************************************************************************/
2877 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
2879 const char *dname
= NULL
;
2881 void *dirptr
= OpenDir(conn
, directory
, False
);
2886 while((dname
= ReadDirName(dirptr
))) {
2890 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2893 /* Construct the full name. */
2894 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
2900 pstrcpy(fullname
, directory
);
2901 pstrcat(fullname
, "/");
2902 pstrcat(fullname
, dname
);
2904 if(VFS_LSTAT(conn
,fullname
, &st
) != 0) {
2909 if(st
.st_mode
& S_IFDIR
) {
2910 if(recursive_rmdir(conn
, fullname
)!=0) {
2914 if(VFS_RMDIR(conn
,fullname
) != 0) {
2918 } else if(VFS_UNLINK(conn
,fullname
) != 0) {
2927 /****************************************************************************
2928 The internals of the rmdir code - called elsewhere.
2929 ****************************************************************************/
2931 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
2935 ok
= (VFS_RMDIR(conn
,directory
) == 0);
2936 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
2938 * Check to see if the only thing in this directory are
2939 * vetoed files/directories. If so then delete them and
2940 * retry. If we fail to delete any of them (and we *don't*
2941 * do a recursive delete) then fail the rmdir.
2943 BOOL all_veto_files
= True
;
2945 void *dirptr
= OpenDir(conn
, directory
, False
);
2947 if(dirptr
!= NULL
) {
2948 int dirpos
= TellDir(dirptr
);
2949 while ((dname
= ReadDirName(dirptr
))) {
2950 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2952 if(!IS_VETO_PATH(conn
, dname
)) {
2953 all_veto_files
= False
;
2958 if(all_veto_files
) {
2959 SeekDir(dirptr
,dirpos
);
2960 while ((dname
= ReadDirName(dirptr
))) {
2964 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2967 /* Construct the full name. */
2968 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
2973 pstrcpy(fullname
, directory
);
2974 pstrcat(fullname
, "/");
2975 pstrcat(fullname
, dname
);
2977 if(VFS_LSTAT(conn
,fullname
, &st
) != 0)
2979 if(st
.st_mode
& S_IFDIR
) {
2980 if(lp_recursive_veto_delete(SNUM(conn
))) {
2981 if(recursive_rmdir(conn
, fullname
) != 0)
2984 if(VFS_RMDIR(conn
,fullname
) != 0)
2986 } else if(VFS_UNLINK(conn
,fullname
) != 0)
2990 /* Retry the rmdir */
2991 ok
= (VFS_RMDIR(conn
,directory
) == 0);
3001 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3006 /****************************************************************************
3008 ****************************************************************************/
3010 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3015 BOOL bad_path
= False
;
3016 SMB_STRUCT_STAT sbuf
;
3017 START_PROFILE(SMBrmdir
);
3019 srvstr_pull_buf(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), STR_TERMINATE
);
3021 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3023 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3025 if (check_name(directory
,conn
)) {
3026 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3027 ok
= rmdir_internals(conn
, directory
);
3031 set_bad_path_error(errno
, bad_path
);
3032 END_PROFILE(SMBrmdir
);
3033 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3036 outsize
= set_message(outbuf
,0,0,True
);
3038 DEBUG( 3, ( "rmdir %s\n", directory
) );
3040 END_PROFILE(SMBrmdir
);
3044 /*******************************************************************
3045 Resolve wildcards in a filename rename.
3046 ********************************************************************/
3048 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
3050 fstring root1
,root2
;
3052 char *p
,*p2
, *pname1
, *pname2
;
3053 int available_space
;
3056 pname1
= strrchr_m(name1
,'/');
3057 pname2
= strrchr_m(name2
,'/');
3059 if (!pname1
|| !pname2
)
3062 fstrcpy(root1
,pname1
);
3063 fstrcpy(root2
,pname2
);
3064 p
= strrchr_m(root1
,'.');
3071 p
= strrchr_m(root2
,'.');
3105 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
3108 snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
3110 pstrcpy_base(pname2
, root2
, name2
);
3116 /****************************************************************************
3117 The guts of the rename command, split out so it may be called by the NT SMB
3119 ****************************************************************************/
3121 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, BOOL replace_if_exists
)
3125 pstring newname_last_component
;
3128 BOOL bad_path1
= False
;
3129 BOOL bad_path2
= False
;
3131 NTSTATUS error
= NT_STATUS_OK
;
3133 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3135 *directory
= *mask
= 0;
3137 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3138 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,&sbuf2
);
3141 * Split the old name into directory and last component
3142 * strings. Note that unix_convert may have stripped off a
3143 * leading ./ from both name and newname if the rename is
3144 * at the root of the share. We need to make sure either both
3145 * name and newname contain a / character or neither of them do
3146 * as this is checked in resolve_wildcards().
3149 p
= strrchr_m(name
,'/');
3151 pstrcpy(directory
,".");
3155 pstrcpy(directory
,name
);
3157 *p
= '/'; /* Replace needed for exceptional test below. */
3161 * We should only check the mangled cache
3162 * here if unix_convert failed. This means
3163 * that the path in 'mask' doesn't exist
3164 * on the file system and so we need to look
3165 * for a possible mangle. This patch from
3166 * Tine Smukavec <valentin.smukavec@hermes.si>.
3169 if (!rc
&& mangle_is_mangled(mask
))
3170 mangle_check_cache( mask
);
3172 has_wild
= ms_has_wild(mask
);
3176 * No wildcards - just process the one file.
3178 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3180 /* Add a terminating '/' to the directory name. */
3181 pstrcat(directory
,"/");
3182 pstrcat(directory
,mask
);
3184 /* Ensure newname contains a '/' also */
3185 if(strrchr_m(newname
,'/') == 0) {
3188 pstrcpy(tmpstr
, "./");
3189 pstrcat(tmpstr
, newname
);
3190 pstrcpy(newname
, tmpstr
);
3193 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3194 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3195 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3196 newname
, newname_last_component
, is_short_name
));
3199 * Check for special case with case preserving and not
3200 * case sensitive, if directory and newname are identical,
3201 * and the old last component differs from the original
3202 * last component only by case, then we should allow
3203 * the rename (user is trying to change the case of the
3206 if((case_sensitive
== False
) &&
3207 (((case_preserve
== True
) &&
3208 (is_short_name
== False
)) ||
3209 ((short_case_preserve
== True
) &&
3210 (is_short_name
== True
))) &&
3211 strcsequal(directory
, newname
)) {
3212 pstring newname_modified_last_component
;
3215 * Get the last component of the modified name.
3216 * Note that we guarantee that newname contains a '/'
3219 p
= strrchr_m(newname
,'/');
3220 pstrcpy(newname_modified_last_component
,p
+1);
3222 if(strcsequal(newname_modified_last_component
,
3223 newname_last_component
) == False
) {
3225 * Replace the modified last component with
3228 pstrcpy(p
+1, newname_last_component
);
3232 resolve_wildcards(directory
,newname
);
3235 * The source object must exist.
3238 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3239 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3240 directory
,newname
));
3242 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3244 * Must return different errors depending on whether the parent
3245 * directory existed or not.
3248 p
= strrchr_m(directory
, '/');
3250 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3252 if (vfs_object_exist(conn
, directory
, NULL
))
3253 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3254 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3256 error
= map_nt_error_from_unix(errno
);
3257 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3258 nt_errstr(error
), directory
,newname
));
3263 error
= can_rename(directory
,conn
,&sbuf1
);
3265 if (!NT_STATUS_IS_OK(error
)) {
3266 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3267 nt_errstr(error
), directory
,newname
));
3272 * If the src and dest names are identical - including case,
3273 * don't do the rename, just return success.
3276 if (strcsequal(directory
, newname
)) {
3277 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3278 return NT_STATUS_OK
;
3281 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3282 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3283 directory
,newname
));
3284 return NT_STATUS_OBJECT_NAME_COLLISION
;
3287 if(VFS_RENAME(conn
,directory
, newname
) == 0) {
3288 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3289 directory
,newname
));
3290 return NT_STATUS_OK
;
3293 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3294 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3296 error
= map_nt_error_from_unix(errno
);
3298 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3299 nt_errstr(error
), directory
,newname
));
3304 * Wildcards - process each file that matches.
3306 void *dirptr
= NULL
;
3310 if (check_name(directory
,conn
))
3311 dirptr
= OpenDir(conn
, directory
, True
);
3314 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3316 if (strequal(mask
,"????????.???"))
3319 while ((dname
= ReadDirName(dirptr
))) {
3322 pstrcpy(fname
,dname
);
3324 if(!mask_match(fname
, mask
, case_sensitive
))
3327 error
= NT_STATUS_ACCESS_DENIED
;
3328 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3329 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3330 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3331 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(error
)));
3334 error
= can_rename(fname
,conn
,&sbuf1
);
3335 if (!NT_STATUS_IS_OK(error
)) {
3336 DEBUG(6,("rename %s refused\n", fname
));
3339 pstrcpy(destname
,newname
);
3341 if (!resolve_wildcards(fname
,destname
)) {
3342 DEBUG(6,("resolve_wildcards %s %s failed\n",
3347 if (!replace_if_exists
&&
3348 vfs_file_exist(conn
,destname
, NULL
)) {
3349 DEBUG(6,("file_exist %s\n", destname
));
3350 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3354 if (!VFS_RENAME(conn
,fname
,destname
))
3356 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3362 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3363 error
= map_nt_error_from_unix(errno
);
3369 /****************************************************************************
3371 ****************************************************************************/
3373 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3382 START_PROFILE(SMBmv
);
3384 p
= smb_buf(inbuf
) + 1;
3385 p
+= srvstr_pull_buf(inbuf
, name
, p
, sizeof(name
), STR_TERMINATE
);
3387 p
+= srvstr_pull_buf(inbuf
, newname
, p
, sizeof(newname
), STR_TERMINATE
);
3389 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3390 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3392 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3394 status
= rename_internals(conn
, name
, newname
, False
);
3395 if (!NT_STATUS_IS_OK(status
)) {
3396 return ERROR_NT(status
);
3400 * Win2k needs a changenotify request response before it will
3401 * update after a rename..
3403 process_pending_change_notify_queue((time_t)0);
3404 outsize
= set_message(outbuf
,0,0,True
);
3410 /*******************************************************************
3411 Copy a file as part of a reply_copy.
3412 ******************************************************************/
3414 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3415 int count
,BOOL target_is_directory
, int *err_ret
)
3418 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3420 files_struct
*fsp1
,*fsp2
;
3425 pstrcpy(dest
,dest1
);
3426 if (target_is_directory
) {
3427 char *p
= strrchr_m(src
,'/');
3436 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3439 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3440 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3445 if (!target_is_directory
&& count
)
3446 ofun
= FILE_EXISTS_OPEN
;
3448 if (VFS_STAT(conn
,dest
,&sbuf2
) == -1)
3449 ZERO_STRUCTP(&sbuf2
);
3451 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3452 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3455 close_file(fsp1
,False
);
3459 if ((ofun
&3) == 1) {
3460 if(VFS_LSEEK(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3461 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
3463 * Stop the copy from occurring.
3466 src_sbuf
.st_size
= 0;
3470 if (src_sbuf
.st_size
)
3471 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
3473 close_file(fsp1
,False
);
3475 /* Ensure the modtime is set correctly on the destination file. */
3476 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
3479 * As we are opening fsp1 read-only we only expect
3480 * an error on close on fsp2 if we are out of space.
3481 * Thus we don't look at the error return from the
3484 *err_ret
= close_file(fsp2
,False
);
3486 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
3489 /****************************************************************************
3490 Reply to a file copy.
3491 ****************************************************************************/
3493 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3498 pstring mask
,newname
;
3501 int error
= ERRnoaccess
;
3505 int tid2
= SVAL(inbuf
,smb_vwv0
);
3506 int ofun
= SVAL(inbuf
,smb_vwv1
);
3507 int flags
= SVAL(inbuf
,smb_vwv2
);
3508 BOOL target_is_directory
=False
;
3509 BOOL bad_path1
= False
;
3510 BOOL bad_path2
= False
;
3512 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3514 START_PROFILE(SMBcopy
);
3516 *directory
= *mask
= 0;
3519 p
+= srvstr_pull_buf(inbuf
, name
, p
, sizeof(name
), STR_TERMINATE
);
3520 p
+= srvstr_pull_buf(inbuf
, newname
, p
, sizeof(newname
), STR_TERMINATE
);
3522 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3524 if (tid2
!= conn
->cnum
) {
3525 /* can't currently handle inter share copies XXXX */
3526 DEBUG(3,("Rejecting inter-share copy\n"));
3527 END_PROFILE(SMBcopy
);
3528 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
3531 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3532 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3534 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3535 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
3537 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
3539 if ((flags
&1) && target_is_directory
) {
3540 END_PROFILE(SMBcopy
);
3541 return ERROR_DOS(ERRDOS
,ERRbadfile
);
3544 if ((flags
&2) && !target_is_directory
) {
3545 END_PROFILE(SMBcopy
);
3546 return ERROR_DOS(ERRDOS
,ERRbadpath
);
3549 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
3550 /* wants a tree copy! XXXX */
3551 DEBUG(3,("Rejecting tree copy\n"));
3552 END_PROFILE(SMBcopy
);
3553 return ERROR_DOS(ERRSRV
,ERRerror
);
3556 p
= strrchr_m(name
,'/');
3558 pstrcpy(directory
,"./");
3562 pstrcpy(directory
,name
);
3567 * We should only check the mangled cache
3568 * here if unix_convert failed. This means
3569 * that the path in 'mask' doesn't exist
3570 * on the file system and so we need to look
3571 * for a possible mangle. This patch from
3572 * Tine Smukavec <valentin.smukavec@hermes.si>.
3575 if (!rc
&& mangle_is_mangled(mask
))
3576 mangle_check_cache( mask
);
3578 has_wild
= ms_has_wild(mask
);
3581 pstrcat(directory
,"/");
3582 pstrcat(directory
,mask
);
3583 if (resolve_wildcards(directory
,newname
) &&
3584 copy_file(directory
,newname
,conn
,ofun
, count
,target_is_directory
,&err
))
3588 END_PROFILE(SMBcopy
);
3589 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3592 exists
= vfs_file_exist(conn
,directory
,NULL
);
3595 void *dirptr
= NULL
;
3599 if (check_name(directory
,conn
))
3600 dirptr
= OpenDir(conn
, directory
, True
);
3605 if (strequal(mask
,"????????.???"))
3608 while ((dname
= ReadDirName(dirptr
))) {
3610 pstrcpy(fname
,dname
);
3612 if(!mask_match(fname
, mask
, case_sensitive
))
3615 error
= ERRnoaccess
;
3616 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
3617 pstrcpy(destname
,newname
);
3618 if (resolve_wildcards(fname
,destname
) &&
3619 copy_file(fname
,destname
,conn
,ofun
,
3620 count
,target_is_directory
,&err
))
3622 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3630 /* Error on close... */
3632 END_PROFILE(SMBcopy
);
3633 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3637 END_PROFILE(SMBcopy
);
3638 return ERROR_DOS(ERRDOS
,error
);
3640 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
3641 unix_ERR_class
= ERRDOS
;
3642 unix_ERR_code
= ERRbadpath
;
3644 END_PROFILE(SMBcopy
);
3645 return(UNIXERROR(ERRDOS
,error
));
3649 outsize
= set_message(outbuf
,1,0,True
);
3650 SSVAL(outbuf
,smb_vwv0
,count
);
3652 END_PROFILE(SMBcopy
);
3656 /****************************************************************************
3658 ****************************************************************************/
3660 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3667 START_PROFILE(pathworks_setdir
);
3670 if (!CAN_SETDIR(snum
)) {
3671 END_PROFILE(pathworks_setdir
);
3672 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3675 srvstr_pull_buf(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), STR_TERMINATE
);
3677 if (strlen(newdir
) == 0) {
3680 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
3682 string_set(&conn
->connectpath
,newdir
);
3686 END_PROFILE(pathworks_setdir
);
3687 return ERROR_DOS(ERRDOS
,ERRbadpath
);
3690 outsize
= set_message(outbuf
,0,0,True
);
3691 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
3693 DEBUG(3,("setdir %s\n", newdir
));
3695 END_PROFILE(pathworks_setdir
);
3699 /****************************************************************************
3700 Get a lock pid, dealing with large count requests.
3701 ****************************************************************************/
3703 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
3705 if(!large_file_format
)
3706 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
3708 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
3711 /****************************************************************************
3712 Get a lock count, dealing with large count requests.
3713 ****************************************************************************/
3715 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
3717 SMB_BIG_UINT count
= 0;
3719 if(!large_file_format
) {
3720 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
3723 #if defined(HAVE_LONGLONG)
3724 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
3725 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
3726 #else /* HAVE_LONGLONG */
3729 * NT4.x seems to be broken in that it sends large file (64 bit)
3730 * lockingX calls even if the CAP_LARGE_FILES was *not*
3731 * negotiated. For boxes without large unsigned ints truncate the
3732 * lock count by dropping the top 32 bits.
3735 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
3736 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3737 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
3738 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
3739 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
3742 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
3743 #endif /* HAVE_LONGLONG */
3749 #if !defined(HAVE_LONGLONG)
3750 /****************************************************************************
3751 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3752 ****************************************************************************/
3754 static uint32
map_lock_offset(uint32 high
, uint32 low
)
3758 uint32 highcopy
= high
;
3761 * Try and find out how many significant bits there are in high.
3764 for(i
= 0; highcopy
; i
++)
3768 * We use 31 bits not 32 here as POSIX
3769 * lock offsets may not be negative.
3772 mask
= (~0) << (31 - i
);
3775 return 0; /* Fail. */
3781 #endif /* !defined(HAVE_LONGLONG) */
3783 /****************************************************************************
3784 Get a lock offset, dealing with large offset requests.
3785 ****************************************************************************/
3787 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
3789 SMB_BIG_UINT offset
= 0;
3793 if(!large_file_format
) {
3794 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
3797 #if defined(HAVE_LONGLONG)
3798 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
3799 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
3800 #else /* HAVE_LONGLONG */
3803 * NT4.x seems to be broken in that it sends large file (64 bit)
3804 * lockingX calls even if the CAP_LARGE_FILES was *not*
3805 * negotiated. For boxes without large unsigned ints mangle the
3806 * lock offset by mapping the top 32 bits onto the lower 32.
3809 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
3810 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
3811 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
3814 if((new_low
= map_lock_offset(high
, low
)) == 0) {
3816 return (SMB_BIG_UINT
)-1;
3819 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3820 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
3821 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
3822 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
3825 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
3826 #endif /* HAVE_LONGLONG */
3832 /****************************************************************************
3833 Reply to a lockingX request.
3834 ****************************************************************************/
3836 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3838 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
3839 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
3840 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
3841 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
3842 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
3843 SMB_BIG_UINT count
= 0, offset
= 0;
3845 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
3848 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
3852 START_PROFILE(SMBlockingX
);
3854 CHECK_FSP(fsp
,conn
);
3856 data
= smb_buf(inbuf
);
3858 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
3859 /* we don't support these - and CANCEL_LOCK makes w2k
3860 and XP reboot so I don't really want to be
3861 compatible! (tridge) */
3862 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
3865 /* Check if this is an oplock break on a file
3866 we have granted an oplock on.
3868 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
3869 /* Client can insist on breaking to none. */
3870 BOOL break_to_none
= (oplocklevel
== 0);
3872 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3873 (unsigned int)oplocklevel
, fsp
->fnum
));
3876 * Make sure we have granted an exclusive or batch oplock on this file.
3879 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
3880 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3881 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
3883 /* if this is a pure oplock break request then don't send a reply */
3884 if (num_locks
== 0 && num_ulocks
== 0) {
3885 END_PROFILE(SMBlockingX
);
3888 END_PROFILE(SMBlockingX
);
3889 return ERROR_DOS(ERRDOS
,ERRlock
);
3893 if (remove_oplock(fsp
, break_to_none
) == False
) {
3894 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3898 /* if this is a pure oplock break request then don't send a reply */
3899 if (num_locks
== 0 && num_ulocks
== 0) {
3900 /* Sanity check - ensure a pure oplock break is not a
3902 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
3903 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3904 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
3905 END_PROFILE(SMBlockingX
);
3911 * We do this check *after* we have checked this is not a oplock break
3912 * response message. JRA.
3915 release_level_2_oplocks_on_change(fsp
);
3917 /* Data now points at the beginning of the list
3918 of smb_unlkrng structs */
3919 for(i
= 0; i
< (int)num_ulocks
; i
++) {
3920 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
3921 count
= get_lock_count( data
, i
, large_file_format
);
3922 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
3925 * There is no error code marked "stupid client bug".... :-).
3928 END_PROFILE(SMBlockingX
);
3929 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3932 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3933 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
3935 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
3936 if (NT_STATUS_V(status
)) {
3937 END_PROFILE(SMBlockingX
);
3938 return ERROR_NT(status
);
3942 /* Setup the timeout in seconds. */
3944 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
3946 /* Now do any requested locks */
3947 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
3949 /* Data now points at the beginning of the list
3950 of smb_lkrng structs */
3952 for(i
= 0; i
< (int)num_locks
; i
++) {
3953 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
3954 count
= get_lock_count( data
, i
, large_file_format
);
3955 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
3958 * There is no error code marked "stupid client bug".... :-).
3961 END_PROFILE(SMBlockingX
);
3962 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3965 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3966 (double)offset
, (double)count
, (unsigned int)lock_pid
,
3967 fsp
->fsp_name
, (int)lock_timeout
));
3969 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
3970 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
));
3971 if (NT_STATUS_V(status
)) {
3972 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
3974 * A blocking lock was requested. Package up
3975 * this smb into a queued request and push it
3976 * onto the blocking lock queue.
3978 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
, lock_pid
, offset
, count
)) {
3979 END_PROFILE(SMBlockingX
);
3987 /* If any of the above locks failed, then we must unlock
3988 all of the previous locks (X/Open spec). */
3989 if (i
!= num_locks
&& num_locks
!= 0) {
3991 * Ensure we don't do a remove on the lock that just failed,
3992 * as under POSIX rules, if we have a lock already there, we
3993 * will delete it (and we shouldn't) .....
3995 for(i
--; i
>= 0; i
--) {
3996 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
3997 count
= get_lock_count( data
, i
, large_file_format
);
3998 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4001 * There is no error code marked "stupid client bug".... :-).
4004 END_PROFILE(SMBlockingX
);
4005 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4008 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4010 END_PROFILE(SMBlockingX
);
4011 return ERROR_NT(status
);
4014 set_message(outbuf
,2,0,True
);
4016 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4017 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4019 END_PROFILE(SMBlockingX
);
4020 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4023 /****************************************************************************
4024 Reply to a SMBreadbmpx (read block multiplex) request.
4025 ****************************************************************************/
4027 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4038 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4039 START_PROFILE(SMBreadBmpx
);
4041 /* this function doesn't seem to work - disable by default */
4042 if (!lp_readbmpx()) {
4043 END_PROFILE(SMBreadBmpx
);
4044 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4047 outsize
= set_message(outbuf
,8,0,True
);
4049 CHECK_FSP(fsp
,conn
);
4052 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
4053 maxcount
= SVAL(inbuf
,smb_vwv3
);
4055 data
= smb_buf(outbuf
);
4056 pad
= ((long)data
)%4;
4061 max_per_packet
= bufsize
-(outsize
+pad
);
4065 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4066 END_PROFILE(SMBreadBmpx
);
4067 return ERROR_DOS(ERRDOS
,ERRlock
);
4071 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4073 nread
= read_file(fsp
,data
,startpos
,N
);
4078 if (nread
< (ssize_t
)N
)
4079 tcount
= total_read
+ nread
;
4081 set_message(outbuf
,8,nread
,False
);
4082 SIVAL(outbuf
,smb_vwv0
,startpos
);
4083 SSVAL(outbuf
,smb_vwv2
,tcount
);
4084 SSVAL(outbuf
,smb_vwv6
,nread
);
4085 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4087 if (!send_smb(smbd_server_fd(),outbuf
))
4088 exit_server("reply_readbmpx: send_smb failed.");
4090 total_read
+= nread
;
4092 } while (total_read
< (ssize_t
)tcount
);
4094 END_PROFILE(SMBreadBmpx
);
4098 /****************************************************************************
4099 Reply to a SMBsetattrE.
4100 ****************************************************************************/
4102 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4104 struct utimbuf unix_times
;
4106 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4107 START_PROFILE(SMBsetattrE
);
4109 outsize
= set_message(outbuf
,0,0,True
);
4111 if(!fsp
|| (fsp
->conn
!= conn
)) {
4112 END_PROFILE(SMBgetattrE
);
4113 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4117 * Convert the DOS times into unix times. Ignore create
4118 * time as UNIX can't set this.
4121 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4122 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4125 * Patch from Ray Frush <frush@engr.colostate.edu>
4126 * Sometimes times are sent as zero - ignore them.
4129 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4130 /* Ignore request */
4131 if( DEBUGLVL( 3 ) ) {
4132 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4133 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4135 END_PROFILE(SMBsetattrE
);
4137 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4138 /* set modify time = to access time if modify time was 0 */
4139 unix_times
.modtime
= unix_times
.actime
;
4142 /* Set the date on this file */
4143 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4144 END_PROFILE(SMBsetattrE
);
4145 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4148 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4149 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4151 END_PROFILE(SMBsetattrE
);
4156 /* Back from the dead for OS/2..... JRA. */
4158 /****************************************************************************
4159 Reply to a SMBwritebmpx (write block multiplex primary) request.
4160 ****************************************************************************/
4162 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4165 ssize_t nwritten
= -1;
4172 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4173 START_PROFILE(SMBwriteBmpx
);
4175 CHECK_FSP(fsp
,conn
);
4179 tcount
= SVAL(inbuf
,smb_vwv1
);
4180 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
4181 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4182 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4183 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4185 data
= smb_base(inbuf
) + smb_doff
;
4187 /* If this fails we need to send an SMBwriteC response,
4188 not an SMBwritebmpx - set this up now so we don't forget */
4189 SCVAL(outbuf
,smb_com
,SMBwritec
);
4191 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4192 END_PROFILE(SMBwriteBmpx
);
4193 return(ERROR_DOS(ERRDOS
,ERRlock
));
4196 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4198 if(lp_syncalways(SNUM(conn
)) || write_through
)
4199 sync_file(conn
,fsp
);
4201 if(nwritten
< (ssize_t
)numtowrite
) {
4202 END_PROFILE(SMBwriteBmpx
);
4203 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4206 /* If the maximum to be written to this file
4207 is greater than what we just wrote then set
4208 up a secondary struct to be attached to this
4209 fd, we will use this to cache error messages etc. */
4211 if((ssize_t
)tcount
> nwritten
) {
4212 write_bmpx_struct
*wbms
;
4213 if(fsp
->wbmpx_ptr
!= NULL
)
4214 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4216 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4218 DEBUG(0,("Out of memory in reply_readmpx\n"));
4219 END_PROFILE(SMBwriteBmpx
);
4220 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4222 wbms
->wr_mode
= write_through
;
4223 wbms
->wr_discard
= False
; /* No errors yet */
4224 wbms
->wr_total_written
= nwritten
;
4225 wbms
->wr_errclass
= 0;
4227 fsp
->wbmpx_ptr
= wbms
;
4230 /* We are returning successfully, set the message type back to
4232 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4234 outsize
= set_message(outbuf
,1,0,True
);
4236 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4238 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4239 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4241 if (write_through
&& tcount
==nwritten
) {
4242 /* We need to send both a primary and a secondary response */
4243 smb_setlen(outbuf
,outsize
- 4);
4244 if (!send_smb(smbd_server_fd(),outbuf
))
4245 exit_server("reply_writebmpx: send_smb failed.");
4247 /* Now the secondary */
4248 outsize
= set_message(outbuf
,1,0,True
);
4249 SCVAL(outbuf
,smb_com
,SMBwritec
);
4250 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4253 END_PROFILE(SMBwriteBmpx
);
4257 /****************************************************************************
4258 Reply to a SMBwritebs (write block multiplex secondary) request.
4259 ****************************************************************************/
4261 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4264 ssize_t nwritten
= -1;
4271 write_bmpx_struct
*wbms
;
4272 BOOL send_response
= False
;
4273 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4274 START_PROFILE(SMBwriteBs
);
4276 CHECK_FSP(fsp
,conn
);
4279 tcount
= SVAL(inbuf
,smb_vwv1
);
4280 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
4281 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4282 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4284 data
= smb_base(inbuf
) + smb_doff
;
4286 /* We need to send an SMBwriteC response, not an SMBwritebs */
4287 SCVAL(outbuf
,smb_com
,SMBwritec
);
4289 /* This fd should have an auxiliary struct attached,
4290 check that it does */
4291 wbms
= fsp
->wbmpx_ptr
;
4293 END_PROFILE(SMBwriteBs
);
4297 /* If write through is set we can return errors, else we must cache them */
4298 write_through
= wbms
->wr_mode
;
4300 /* Check for an earlier error */
4301 if(wbms
->wr_discard
) {
4302 END_PROFILE(SMBwriteBs
);
4303 return -1; /* Just discard the packet */
4306 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4308 if(lp_syncalways(SNUM(conn
)) || write_through
)
4309 sync_file(conn
,fsp
);
4311 if (nwritten
< (ssize_t
)numtowrite
) {
4313 /* We are returning an error - we can delete the aux struct */
4316 fsp
->wbmpx_ptr
= NULL
;
4317 END_PROFILE(SMBwriteBs
);
4318 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4320 END_PROFILE(SMBwriteBs
);
4321 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4324 /* Increment the total written, if this matches tcount
4325 we can discard the auxiliary struct (hurrah !) and return a writeC */
4326 wbms
->wr_total_written
+= nwritten
;
4327 if(wbms
->wr_total_written
>= tcount
) {
4328 if (write_through
) {
4329 outsize
= set_message(outbuf
,1,0,True
);
4330 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4331 send_response
= True
;
4335 fsp
->wbmpx_ptr
= NULL
;
4339 END_PROFILE(SMBwriteBs
);
4343 END_PROFILE(SMBwriteBs
);
4347 /****************************************************************************
4348 Reply to a SMBgetattrE.
4349 ****************************************************************************/
4351 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4353 SMB_STRUCT_STAT sbuf
;
4356 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4357 START_PROFILE(SMBgetattrE
);
4359 outsize
= set_message(outbuf
,11,0,True
);
4361 if(!fsp
|| (fsp
->conn
!= conn
)) {
4362 END_PROFILE(SMBgetattrE
);
4363 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4366 /* Do an fstat on this file */
4367 if(fsp_stat(fsp
, &sbuf
)) {
4368 END_PROFILE(SMBgetattrE
);
4369 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4372 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4375 * Convert the times into dos times. Set create
4376 * date to be last modify date as UNIX doesn't save
4380 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4381 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4382 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4385 SIVAL(outbuf
,smb_vwv6
,0);
4386 SIVAL(outbuf
,smb_vwv8
,0);
4388 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4389 SIVAL(outbuf
,smb_vwv8
,SMB_ROUNDUP(sbuf
.st_size
,1024));
4391 SSVAL(outbuf
,smb_vwv10
, mode
);
4393 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4395 END_PROFILE(SMBgetattrE
);